How can I control the visibility of dynamically created controls via the context menu?

I have an ItemControl that binds to a list of properties in my ViewModel and using the DataTemplate will automatically generate the appropriate control based on the type of the property.

Here is the code for the ItemsControl:

<ItemsControl Grid.Column="0" ItemsSource="{Binding Properties}" >
    <ItemsControl.Resources>
        <DataTemplate x:Key="StringTemplate" DataType="{x:Type ui:ControlStringData}" >
            <xctk:WatermarkTextBox Text="{Binding Path=Text, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
                                        Watermark="{Binding Path=Caption, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
                                        Margin="5,5,5,5" />
        </DataTemplate>
        <DataTemplate x:Key="DateTimeTemplate" DataType="{x:Type ui:ControlDateTimeData}">
            <xctk:DateTimePicker Value="{Binding Path=Value, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
                                        Watermark="{Binding Path=Caption, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
                                        Margin="5,5,5,5" />
        </DataTemplate>
        <DataTemplate x:Key="DefaultTemplate" />
    </ItemsControl.Resources>
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <ContentControl
                    x:Name="MyContentControl"
                    Content="{Binding}"
                    ContentTemplate="{StaticResource DefaultTemplate}"/>
            <DataTemplate.Triggers>
                <DataTrigger Binding="{Binding Path=Type}" Value="DateTime">
                    <Setter TargetName="MyContentControl" Property="ContentTemplate"
                                Value="{StaticResource DateTimeTemplate}" />
                </DataTrigger>
                <DataTrigger Binding="{Binding Path=Type}" Value="String">
                    <Setter TargetName="MyContentControl" Property="ContentTemplate"
                                Value="{StaticResource StringTemplate}" />
                </DataTrigger>
            </DataTemplate.Triggers>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <UniformGrid />
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
</ItemsControl>

      

Now, given the generated control, I would like to create a ContextMenu filled with a Caption property and a checkbox, where each item in the ContextMenu is bound to the visibility of the corresponding control.

The current code has a button that will open a context menu:

<Button Margin="5,5,5,5" Grid.Column="1" Grid.Row="0" Height="16" Width="16">
    <Button.Style>
        <Style TargetType="{x:Type Button}">
            <Style.Triggers>
                <EventTrigger RoutedEvent="Click">
                    <EventTrigger.Actions>
                        <BeginStoryboard>
                            <Storyboard>
                                <BooleanAnimationUsingKeyFrames Storyboard.TargetProperty="ContextMenu.IsOpen">
                                    <DiscreteBooleanKeyFrame KeyTime="0:0:0" Value="True"/>
                                </BooleanAnimationUsingKeyFrames>
                            </Storyboard>
                        </BeginStoryboard>
                    </EventTrigger.Actions>
                </EventTrigger>
            </Style.Triggers>
            <Setter Property="ContextMenu">
                <Setter.Value>
                    <ContextMenu />

                </Setter.Value>
            </Setter>
        </Style>
    </Button.Style>
</Button>

      

How do I create a context menu and restrict visibility? I am stuck as I am not sure how to properly set up the bindings for this.

More details:

So, in the above ItemsControl, it binds to a list of properties called Properties, where each item implements:

public interface IControlData
{
    string Type { get; set; }
    string Name { get; set; }
    string Caption { get; set; }
    bool Visibility { get; set; }
}

      

As per the type string, I use the data triggers in the above example to create the correct control for that type, and they are placed in the ItemsControl, which is the template for the UniformGrid.

Now I would like to have a button that, when clicked, presents a list of names of each control in the ItemsControl, and each entry can be checked, where the checked state matches the visibility of the control in the ItemsControl.

Example: If the ItemsControl grid is this:

+----------+----------+
| TextBox1 | TextBox2 |
+----------+----------+
| TextBox3 | TextBox4 |
+----------+----------+

      

Then the context menu displayed when the button is clicked will be:

+---+----------+
| βœ“ | TextBox1 |
| βœ“ | TextBox2 |
| βœ“ | TextBox3 |
| βœ“ | TextBox4 |
+---+----------+

      

If I click one of the entries in the ContextMenu, say for example TextBox4, this sets the visibility of TextBox4 to false and the control looks like this:

+----------+----------+
| TextBox1 | TextBox2 |
+----------+----------+
| TextBox3 |          |
+----------+----------+

      

And the context menu will look like:

+---+----------+
| βœ“ | TextBox1 |
| βœ“ | TextBox2 |
| βœ“ | TextBox3 |
|   | TextBox4 |
+---+----------+

      

+3


source to share


1 answer


Use DataTemplateSelector.

This class is designed to handle options for various state-based data templates.



http://msdn.microsoft.com/en-us/library/system.windows.controls.datatemplateselector(v=vs.110).aspx

0


source







All Articles