WPF在触发器上更改Grid.ColumnSpan

时间:2009-12-04 17:03:50

标签: c# wpf xaml mvvm

tl; dr:如果选择了2个项目,我希望详细视图显示在2列中;如果只选择了1个项目,则希望显示2列。

我有一个DockPanel,左边有两个ListBox,右边有一个2列Grid。

在listBox1中选择某个项目时,我会在网格的第0列中显示详细信息视图。

在listBox2中选择某个项目时,我会在网格的第1列中显示详细信息视图。

    <DockPanel>

        <StackPanel DockPanel.Dock="Left" Orientation="Horizontal">
            <ListBox x:Name="listBox1" ItemsSource="{Binding Items1}" SelectedItem="{Binding SelectedItem1}"/>                    
            <ListBox x:Name="listBox2" ItemsSource="{Binding Items2}" SelectedItem="{Binding SelectedItem2}"/>
        </StackPanel>

        <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="*" />
                <ColumnDefinition Width="*" />
            </Grid.ColumnDefinitions>

            <ContentControl Grid.Column="0" Content="{Binding SelectedItem1}" ContentTemplateSelector="{StaticResource SelectedItemTemplateSelector}"/>
            <ContentControl Grid.Column="1" Content="{Binding SelectedItem2}" ContentTemplateSelector="{StaticResource SelectedItemTemplateSelector}"/>
        </Grid>

    </DockPanel>

这很好用。但是,我想修改它,以便当其中一个列表框中选择了某个项而不是另一个列表框中的项时,详细信息视图将跨越两个网格列

我的第一个想法是创建一些DataTriggers,它们根据ListBoxes的SelectedIndex修改ContentControls的ColumnSpan。

这适用于通常位于Grid.Column =“0”的详细信息视图。但是,它不适用于通常位于Grid.Column =“1”的详细信息视图,因为原始列号是硬编码的:

            <ContentControl Grid.Column="0" Content="{Binding SelectedItem1}" ContentTemplateSelector="{StaticResource SelectedItemTemplateSelector}">
                <ContentControl.Style>
                    <Style TargetType="ContentControl">
                        <Style.Triggers>
                            <DataTrigger Binding="{Binding ElementName=listBox2, Path=SelectedIndex}" Value="-1">
                                <Setter Property="Grid.ColumnSpan" Value="2"/>
                            </DataTrigger>
                        </Style.Triggers>
                    </Style>
                </ContentControl.Style>
            </ContentControl>

            <ContentControl Grid.Column="1" Content="{Binding SelectedItem2}" ContentTemplateSelector="{StaticResource SelectedItemTemplateSelector}">
                <ContentControl.Style>
                    <Style TargetType="ContentControl">
                        <Style.Triggers>
                            <DataTrigger Binding="{Binding ElementName=listBox1, Path=SelectedIndex}" Value="-1">
                                <!--Can't modify Grid.Column since it's hardcoded above!-->
                                <Setter Property="Grid.Column" Value="0"/>
                                <Setter Property="Grid.ColumnSpan" Value="2"/>
                            </DataTrigger>
                        </Style.Triggers>
                    </Style>
                </ContentControl.Style>
            </ContentControl>

如果我可以创建一个可以对ListBox.SelectedIndex(即&gt; = 0)进行值比较的DataTrigger,那么我可以避免首先对列号进行硬编码。

有没有办法在XAML中做这样的事情?

2 个答案:

答案 0 :(得分:0)

我最终实现了here描述的转换器。

答案 1 :(得分:0)

你总是可以做隐藏的元素绑定技巧。在下面的示例中,您只需将bindme更改为2,并且网格跨度将发生变化。我对你无法用故事板制作动画的所有类型的东西都这样做。

&lt; Rectangle x:Name =“bindme”Width =“0”Height =“0”Tag =“1”/&gt;

&lt; Grid Grid.ColumnSpan =“{Binding Tag,ElementName = bindme}”&gt;