【问题标题】:change checkbox state in DataGridTemplateColumn after row is selected in datagrid using xaml使用 xaml 在数据网格中选择行后更改 DataGridTemplateColumn 中的复选框状态
【发布时间】:2018-01-17 10:29:29
【问题描述】:

我正在创建一个 wpf 应用程序并在一段时间内努力解决这个问题。 我有一个带有 DataGridTemplateColumn 的数据网格,其中包含一个复选框和文本块。

  <DataGrid
        Name="ChargeDataGrid"
        Grid.Row="1"
        AutoGenerateColumns="False">
        <DataGrid.Columns>
            <DataGridTemplateColumn Width="*">
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <StackPanel Orientation="Horizontal">
                            <CheckBox x:Name="CheckBox1"/>
                            <TextBlock Text="{Binding}" />
                        </StackPanel>
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
                <DataGridTemplateColumn.HeaderTemplate>
                    <DataTemplate>
                        <StackPanel Orientation="Horizontal">
                            <CheckBox />
                            <TextBlock Text="Title" />
                        </StackPanel>
                    </DataTemplate>
                </DataGridTemplateColumn.HeaderTemplate>
            </DataGridTemplateColumn>
        </DataGrid.Columns>
        <system:String>123</system:String>
        <system:String>124</system:String>
        <system:String>125</system:String>
        <system:String>126</system:String>
        <system:String>127</system:String>
    </DataGrid>

我需要实现的是,当单击该行时,该行中的复选框也必须处于选中状态。 我尝试使用样式触发器:

<Style TargetType="{x:Type DataGridCell}">
    <Style.Triggers>
        <Trigger Property="IsSelected" Value="True">
            <Setter Property="CheckBox1.IsChecked" Value="True" />
            <Setter Property="Background" Value="Blue" />
        </Trigger>
    </Style.Triggers>
</Style>

但似乎无法像这样更改复选框状态。我知道如何以代码隐藏或 mvvm 样式执行此操作,但在这种情况下,我想知道是否可以仅使用 xaml?

任何帮助将不胜感激。

【问题讨论】:

    标签: c# wpf xaml datagrid


    【解决方案1】:

    我很害怕,但是使用普通的标准 XAML 是做不到的。 我看到你有两个选择:

    1. 您可以使用一些扩展库来扩展绑定的功能。一些功能可以在 mvvm 框架中找到,例如 MugenMvvmToolkit
    2. 第二种选择是为此目的使用一些转换器。

    我对第二种变体的解决方案是一种 hack,在我看来,更优雅的方法是使用代码。转换器:

    public class MultiValueConverter : IMultiValueConverter
    {
        public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
        {  
            if (values.Length != 3) throw new ArgumentException("Should be 3 params");
            if (!(values[2] is FrameworkElement element)) return values[1];
    
            if (!(bool)values[0])
            {
                element.Tag = "Value need to be changed.";
                return values[1];
            }
    
            if (element.Tag.Equals("Value changed.")) return values[1];
            var res = !(bool)(values[1] ?? true);
            element.Tag = "Value changed.";
            return res;
        }
    
        public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }
    

    转换器反转 bool 变量并将先前的状态保存在控件的 Tag 属性中。这仍然不是代码落后且非常可重用的解决方案。您可以在需要此类行为的任何其他视图中使用此类转换器

    在 XAML 中,我只更改了复选框控件定义:

    <CheckBox x:Name="RowCheckBox" IsHitTestVisible="False">
        <CheckBox.IsChecked>
            <MultiBinding Converter="{StaticResource MultiValueConverter}" Mode="OneWay">
                <Binding Path="IsSelected" RelativeSource="{RelativeSource FindAncestor, AncestorType={x:Type DataGridRow}}" />
                <Binding Path="IsChecked" RelativeSource="{RelativeSource Self}" />
                <Binding Mode="OneWay" RelativeSource="{RelativeSource Self}" />
            </MultiBinding>
        </CheckBox.IsChecked>
    </CheckBox>
    

    【讨论】:

      【解决方案2】:

      我认为它可以像这样简单地完成:

      <CheckBox x:Name="CheckBox1" IsChecked="{Binding RelativeSource={RelativeSource AncestorType=DataGridRow}, Path=IsSelected}"/>
      

      编辑:

      如果想要的结果是仅在(重新)选择行时更改 IsChecked 状态,则可以使用 DependencyObject(例如包含窗口)上的附加属性来完成,如下所示:

      1) 将复选框定义为:

      <CheckBox x:Name="CheckBox1" IsEnabled="true" local:MainWindow.CheckboxChecked="{Binding RelativeSource={RelativeSource AncestorType=DataGridRow}, Path=IsSelected,Mode=OneWay}">
      

      2) 如下定义附加属性:

      public static bool GetCheckboxChecked(DependencyObject obj)
      {
        return (bool)obj.GetValue(CheckboxCheckedProperty);
      }
      
      public static void SetCheckboxChecked(DependencyObject obj, bool value)
      {
        obj.SetValue(CheckboxCheckedProperty, value);
      }
      
      public static readonly DependencyProperty CheckboxCheckedProperty =
          DependencyProperty.RegisterAttached("CheckboxChecked", typeof(bool), typeof(MainWindow), new PropertyMetadata(false, CheckboxChecked_Changed));
      private static void CheckboxChecked_Changed(DependencyObject d, DependencyPropertyChangedEventArgs e)
      {
        CheckBox chk = d as CheckBox;
        if (chk != null && chk.Tag == null)
        {
          bool chkValue = chk.IsChecked.GetValueOrDefault();
          bool oldValue = (bool)e.OldValue;
          bool newValue = (bool)e.NewValue;
          chk.Tag = true; // Just to prevent an infinite loop
          chk.IsChecked = !chkValue && !newValue || chkValue && !oldValue && newValue ? false : true;
          chk.Tag = null;
        }
      }
      

      【讨论】:

      • 但在这种情况下,选择将丢失时,将取消选中复选框。据我了解,它不应该是这样,复选框应该保存其选中状态。
      猜你喜欢
      • 2012-03-04
      • 1970-01-01
      • 2015-11-20
      • 2010-11-08
      • 2017-02-01
      • 2020-07-16
      • 2011-11-06
      • 2015-10-11
      • 1970-01-01
      相关资源
      最近更新 更多