MVVM:使用DataGrid CheckBox IsChecked属性来控制相邻的TextBox的TextDecorations

时间:2013-12-18 07:31:54

标签: c# wpf xaml mvvm styles

我需要在不破坏MVVM(没有代码隐藏/事件)的情况下完成以下任务。我有一个带有CheckBox列和TextBox列的DataGrid。如果选中该复选框,我想将TextBox的TextDecorations属性更改为Strikethrough。虽然编译器不讨厌我的XAML,但它不起作用。我的DataGridTextBoxColumn的XAML如下:

<DataGridTextColumn Header="Item Description" Binding="{Binding Path=ItemDescription, Mode=TwoWay}" Width="175">
                        <DataGridTextColumn.ElementStyle>
                            <Style TargetType="TextBlock">
                                <Setter Property="TextWrapping" Value="Wrap"/>
                                <Setter Property="TextAlignment" Value="Center" />
                                <Style.Triggers>
                                    <DataTrigger Binding="{Binding ElementName=complete, Path=IsChecked}" Value="True">
                                        <Setter Property="TextDecorations" Value="Strikethrough"/>
                                    </DataTrigger>
                                </Style.Triggers>
                            </Style>    
                        </DataGridTextColumn.ElementStyle>
                    </DataGridTextColumn>

1 个答案:

答案 0 :(得分:0)

由于 ItemsSource 中的每个元素,DataGrid在运行时创建自己的TextBlock和CheckBox,因此无法通过名称绑定到此元素。相反,您应该将 CheckBox 的Value和 TextBlock 的样式设置器绑定到您的模型。例如,你有这样的Model和ViewModel:

<强>型号:

public class SomeModel : INotifyPropertyChanged
{
    private string textField;
    private bool boolField;
    public event PropertyChangedEventHandler PropertyChanged;

    public string TextField
    {
        get { return textField; }
        set
        {
            if (value == textField) return;
            textField = value;
            OnPropertyChanged();
        }
    }

    public bool BoolField
    {
        get { return boolField; }
        set
        {
            if (value.Equals(boolField)) return;
            boolField = value;
            OnPropertyChanged();
        }
    }

    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        var handler = PropertyChanged;
        if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
    }
}

<强>视图模型:

public class MainViewModel : INotifyPropertyChanged
{
    private ObservableCollection<SomeModel> models;

    public ObservableCollection<SomeModel> Models
    {
        get { return models; }
        set
        {
            if (Equals(value, models)) return;
            models = value;
            OnPropertyChanged();
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    public MainViewModel()
    {
        Models = new ObservableCollection<SomeModel>();
    }

    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        var handler = PropertyChanged;
        if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
    }
}

所以现在你可以将模型的 BoolField 绑定到 CheckBox 的Value和 TextBlock 的View Setters in View:

<强> MainView.cs:

public partial class MainView : Window
{
    public MainView()
    {

        InitializeComponent();
        var mv = new MainViewModel
        {
            Models = { new SomeModel { BoolField = true, TextField = "One" }, new SomeModel { TextField = "Two" } },
        };
        DataContext = mv;

    }
}

<强> MainView.xaml:

<Window x:Class="WpfDataGridCols.MainView"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainView" Height="350" Width="525">
<Grid>
    <DataGrid ItemsSource="{Binding Models}" AutoGenerateColumns="False">
        <DataGrid.Columns>
            <DataGridTextColumn Binding="{Binding TextField}">
                <DataGridTextColumn.ElementStyle>
                    <Style TargetType="TextBlock">
                        <Setter Property="TextWrapping" Value="Wrap"/>
                        <Setter Property="TextAlignment" Value="Center" />
                        <Style.Triggers>
                            <!--Pay attention on this:-->
                            <DataTrigger Binding="{Binding BoolField}" Value="True">
                                <Setter Property="TextDecorations" Value="Strikethrough"/>
                            </DataTrigger>
                        </Style.Triggers>
                    </Style>
                </DataGridTextColumn.ElementStyle>
            </DataGridTextColumn>
            <DataGridCheckBoxColumn Binding="{Binding BoolField}"/>
        </DataGrid.Columns>
    </DataGrid>
</Grid>