【问题标题】:Unable to bind DataTemplateColumn element to another DataTemplateColumn无法将 DataTemplateColumn 元素绑定到另一个 DataTemplateColumn
【发布时间】:2019-05-28 16:59:03
【问题描述】:

我正在尝试通过在同一行中设置另一个元素来在每个 DataGrid 行中设置一个元素。
如果ToggleButton 中的IsChecked 为True,则ContentControl 中的图像将变为可见。

我已经蚕食了这个example 试图让它工作。 This 的例子似乎也很相似,我希望我没有重复任何内容。

这是我的 DataGrid 实现中的代码 sn-p:

<Grid>
    <StackPanel>
        <Grid Margin="0" Grid.Column="0" Grid.Row="3">
            <DataGrid 
              ItemsSource="{Binding Path=. , Mode=OneWay, NotifyOnSourceUpdated=True, UpdateSourceTrigger=PropertyChanged}"   
              AutoGenerateColumns="False" 
              Height="Auto" 
              HorizontalAlignment="Left"               
              VerticalAlignment="Top" 
              ScrollViewer.CanContentScroll="True" 
              ScrollViewer.VerticalScrollBarVisibility="Visible"
              x:Name="Filter_grid"  
              Grid.Row="1">
                <DataGrid.Columns >
                    <DataGridTextColumn Header="CAN ID"  Binding="{Binding Information.CAN_ID}" Width="50" />
                    <DataGridTextColumn Header="Messagen Name" Binding="{Binding Information.CAN_ID_description}" Width="300" />
                    <DataGridTextColumn Binding="{Binding Information.Status}" Width="50" />
                    <DataGridTemplateColumn Header = "Filter ON" Width="SizeToCells" IsReadOnly="True">
                        <DataGridTemplateColumn.CellTemplate>
                            <DataTemplate>
                                <ContentControl Content="{Binding Information.Tick}">
                                    <ContentControl.Style>
                                        <Style TargetType = "ContentControl" >
                                            <Setter Property="Visibility" Value="Hidden"/>
                                            <Style.Triggers>                                                   
                                                <DataTrigger  Binding = "{Binding  Path=IsChecked, ElementName=Filter_on}" Value="True">
                                                    <Setter Property = "Visibility" Value="Visible"/>
                                                </DataTrigger>
                                            </Style.Triggers>
                                        </Style>
                                    </ContentControl.Style>
                                </ContentControl>
                            </DataTemplate>
                        </DataGridTemplateColumn.CellTemplate>
                    </DataGridTemplateColumn>
                    <DataGridTemplateColumn x:Name="F_column" Header ="Select">
                        <DataGridTemplateColumn.CellTemplate>
                            <DataTemplate>
                                <ToggleButton  x:Name="Filter_on" Content="Switch" />                                                                   
                            </DataTemplate>
                        </DataGridTemplateColumn.CellTemplate>
                    </DataGridTemplateColumn>             
                </DataGrid.Columns>
            </DataGrid>
        </Grid>
    </StackPanel>
</Grid>

我无法获取 ElementName 以找到 ToggleBox 并获取 Cannot find source for binding with reference 'ElementName=Filter_on'

我试过做类似的事情

&lt;DataTrigger Binding="{Binding RelativeSource={RelativeSource AncestorType={x:Type DataGridTemplateColumn}}, Path=F_column.Filter_on}" Value="True"&gt;,或使用x:Reference,这会引发我无法解读的异常。

【问题讨论】:

  • 为什么你会假设其中一列是可视树中另一列的祖先?无论如何,您应该将两者绑定到行视图模型的相同属性。网格中的每一行都有该模板的一个实例。它将如何决定绑定到哪一个?因此,模板中的元素名称仅在模板中才有意义。您的第一个示例没有数据模板;第二个绑定到行视图模型的属性。
  • 请记住,DataGridColumn 不是 UI 中的事物;它告诉 DataGrid 如何在每一行中生成单元格。

标签: c# wpf data-binding datagrid


【解决方案1】:

第一件事:你永远不应该这样做。 XAML 非常灵活,允许您做一些非常聪明的事情,但仅仅因为您可以并不意味着您应该这样做。在这种情况下,正确的解决方案是为每个行元素创建一个视图模型,并使用按钮和数据触发器都可以绑定到的布尔属性。除了更灵活之外,它还更容易测试、调试和记录等。

也就是说,您所要求的在技术上是可行的。由于采用了各种优化等,DataGrid 实际上非常复杂,因此您仍然需要使用中间属性,但由于您不想使用视图模型,因此您必须在按钮的 DataGridCell 中使用 Tag 属性相反(可用于任意用户数据):

  1. 绑定按钮的IsChecked 属性以对它的父DataGridCell 的Tag 属性进行单向源绑定。
  2. 绑定DataTrigger以找到父DataGridCellsPanel,然后直接绑定到相应子的Tag属性,即Children[1].Tag

把它放在一起,你就得到了:

<DataGrid ItemsSource="{Binding Items}" AutoGenerateColumns="False">
    <DataGrid.Columns>

        <DataGridTemplateColumn Header = "Filter ON" Width="SizeToCells" IsReadOnly="True">
            <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <ContentControl>
                        <ContentControl.Style>
                            <Style TargetType = "ContentControl" >
                                <Setter Property="Visibility" Value="Hidden"/>
                                <Style.Triggers>
                                    <DataTrigger  Binding = "{Binding Path=Children[1].Tag, RelativeSource={RelativeSource AncestorType={x:Type DataGridCellsPanel}}}" Value="True">
                                        <Setter Property = "Visibility" Value="Visible"/>
                                    </DataTrigger>
                                </Style.Triggers>
                            </Style>
                        </ContentControl.Style>
                        <TextBlock Text="Content goes here" />
                    </ContentControl>
                </DataTemplate>
            </DataGridTemplateColumn.CellTemplate>
        </DataGridTemplateColumn>


        <DataGridTemplateColumn x:Name="F_column" Header ="Select">
            <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <ToggleButton x:Name="Filter_on" Content="Switch" IsChecked="{Binding Path=Tag, RelativeSource={RelativeSource AncestorType=DataGridCell}, Mode=OneWayToSource}" />
                </DataTemplate>
            </DataGridTemplateColumn.CellTemplate>
        </DataGridTemplateColumn>

    </DataGrid.Columns>

</DataGrid>

但说真的……只需使用视图模型。

【讨论】:

  • 您好,感谢您的详细回答。我想我确实使用了 ViewModel,每一行都有一个模型,它们是在后台代码中分配的。我想看看如何仅在 XAMl 中设置它们,我为相对路径的分配有点挣扎。我已经更新了我的问题中的代码,我无法使用您的代码的第一行,因为我绑定到不同的属性来获取行。
  • 对不起,我没有关注你,你具体指的是哪一行?除了您必须绑定到Children[4].Tag 而不是Children[1].Tag 之外,我在您更新的代码中看不到任何不同之处。两个Tag 绑定都将RelativeSource 用于祖先,因此它们各自的数据上下文绑定不应干扰。
猜你喜欢
  • 1970-01-01
  • 2011-04-24
  • 1970-01-01
  • 2018-06-04
  • 1970-01-01
  • 1970-01-01
  • 2017-11-22
  • 1970-01-01
  • 2020-08-25
相关资源
最近更新 更多