我正在创建一个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?
任何帮助将不胜感激。
答案 0 :(得分:1)
我认为它可以像这样简单地完成:
<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;
}
}
答案 1 :(得分:1)
我很害怕,但是使用简单的标准XAML,你无法做到。 我认为你有两种选择:
我对第二个变体的解决方案是一种破解,在我看来,更优雅的方式是使用代码。转换器:
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>