MVVM:使用DataGrid CheckBox IsChecked属性来控制相邻的TextBox';s Text

本文关键字:TextBox Text 控制 DataGrid 使用 CheckBox IsChecked 属性 MVVM | 更新日期: 2024-10-23 12:25:19

我需要在不破坏MVVM的情况下完成以下操作(无代码隐藏/事件)。我有一个DataGrid,它有一个CheckBox列和一个TextBox列。如果复选框被选中,我想将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>

MVVM:使用DataGrid CheckBox IsChecked属性来控制相邻的TextBox';s Text

因为对于ItemsSourceDataGrid中的每个元素,在运行时都会创建自己的TextBlock和CheckBox,所以不能按名称绑定到这些元素。相反,您应该将复选框的值和文本块的样式设置符都绑定到您的模型。例如,您有这样的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绑定到复选框的值和文本块在视图中的样式设置符:

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>