簡體   English   中英

將DataGridTextColumn的IsReadOnly綁定到DataGridTemplateColumn復選框IsChecked

[英]Binding IsReadOnly of a DataGridTextColumn to a DataGridTemplateColumn checkbox IsChecked

基本上,我有一個DataGrid幾個欄目,我想啟用(改變IsReadOnly屬性)一個DataGridTextColumn基於一個CheckBox IsChecked ,位於另一個DataGridTemplateColumn相同的DataGrid

這是代碼的(重要部分):

<DataGrid Name="lstTags" Grid.Row="0" ItemsSource="{Binding Path = LinesCollection}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" AutoGenerateColumns="False" CanUserAddRows="False" CanUserDeleteRows="False" SelectionMode="Single" LostFocus="lstTags_LostFocus" SelectionChanged="lstTags_SelectionChanged">
    <DataGrid.Columns>
        <DataGridTemplateColumn x:Name="colAutoScale" Header="Auto Scale">
            <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <CheckBox x:Name="ckbAutoScale" HorizontalAlignment="Center" IsChecked="{Binding AutoScale, UpdateSourceTrigger=PropertyChanged}"/>
                 </DataTemplate>
            </DataGridTemplateColumn.CellTemplate>
        </DataGridTemplateColumn>
        <DataGridTextColumn Header="Scale" Binding="{Binding Path=Scale}" IsReadOnly="{Binding ElementName ckbAutoScale, Path=IsChecked}" Width="60" />
    </DataGrid.Columns>
</DataGrid>

值得一提的是,我還想反轉IsChecked屬性的值,即

  • IsChecked = true => IsReadOnly = false ;
  • IsChecked = false => IsReadOnly = true

我可能會用一個簡單的Converter實現此目的,但是我需要第一部分工作。

編輯:

回答一個好問題,我的目標是禁用相鄰的單元格 (同一行),而不是整個列。

這類問題確實是Model-View-ViewModel(MVVM)模式存在的原因。

使用MVVM,您可以綁定到具有支持視圖所需的確切屬性的視圖模型。 這使模型可以更加關注需要保留哪些數據。

因此,對於您的問題,您需要創建一個LineViewModel ,看起來像這樣:

public class LineViewModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    private bool _isAutoScale;
    private double _scale;

    public bool IsAutoScale
    {
        get { return _isAutoScale; }
        set
        {
            if (value == _isAutoScale) return;
            _isAutoScale = value;
            OnPropertyChange("IsAutoScale");
            OnPropertyChange("IsReadOnly");
        }
    }

    public double Scale
    {
        get { return _scale; }
        set
        {
            if (value == _scale) return;
            _scale = value;
            OnPropertyChange("Scale");
        }
    }

    public bool IsReadOnly => !IsAutoScale;

    private void OnPropertyChange(string propertyName)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

同時,您還想創建一個稱為MainWindowViewModel的父視圖模型(或對您的情況有意義的東西)。 這是一個非常原始的版本:

public class MainWindowViewModel : INotifyPropertyChanged
{
    private List<LineViewModel> _lineViewModels;
    public event PropertyChangedEventHandler PropertyChanged;

    public List<LineViewModel> LineViewModels
    {
        get { return _lineViewModels; }
        set
        {
            if (value == _lineViewModels) return;
            _lineViewModels = value;
            OnPropertyChange("LineViewModels");
        }
    }

    public MainWindowViewModel()
    {
        LineViewModels = new[]
        {
            new { AutoScale = false, Scale = 0.2 },
            new { AutoScale = true, Scale = 0.3 },
            new { AutoScale = false, Scale = 0.4 },
        }
            .Select(
                x => new LineViewModel
                {
                    IsAutoScale = x.AutoScale,
                    Scale = x.Scale
                })
            .ToList();
    }

    private void OnPropertyChange(string propertyName)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

最后,您將更新XAML文件,使其看起來像這樣:

<Window x:Class="Sandbox.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:sandbox="clr-namespace:Sandbox"
        mc:Ignorable="d"
        Title="MainWindow"
        Height="350"
        Width="525">
    <Window.DataContext>
        <sandbox:MainWindowViewModel />
    </Window.DataContext>
    <DataGrid ItemsSource="{Binding LineViewModels}"
              HorizontalAlignment="Stretch"
              VerticalAlignment="Stretch"
              AutoGenerateColumns="False"
              CanUserAddRows="False"
              CanUserDeleteRows="False"
              SelectionMode="Single">
        <DataGrid.Columns>
            <DataGridTemplateColumn Header="Auto Scale">
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <CheckBox HorizontalAlignment="Center"
                                  IsChecked="{Binding IsAutoScale}" />
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>
            <DataGridTemplateColumn Header="Auto Scale">
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <TextBox Text="{Binding Scale}"
                                 IsReadOnly="{Binding IsReadOnly}" />
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>
        </DataGrid.Columns>
    </DataGrid>
</Window>

因此,基本上,對於視圖邏輯MainWindow由下式確定MainWindowViewModel並為各行的視圖邏輯DataGrid由受控LineViewModel

請注意,可以使用諸如MVVM Light Toolkit和PropertyChanged.Fody之類的庫/ NuGet包來簡化實現INotifyPropertyChanged的許多樣板。

將以下綁定用於“ Scale Column

 <DataGridTextColumn Header="Scale" Binding="{Binding Path=Scale}" Width="60" >
      <DataGridTextColumn.CellStyle>
           <Style TargetType="DataGridCell">
                <Setter Property="IsEnabled" Value="{Binding RelativeSource={RelativeSource AncestorType={x:Type DataGridCellsPanel}},Path=Children[0].Content.Content.AutoScale}" />
           </Style>
      </DataGridTextColumn.CellStyle>
</DataGridTextColumn>

或者簡單地

<DataGridTextColumn Header="Scale" Binding="{Binding Path=Scale}" Width="60" >
            <DataGridTextColumn.CellStyle>
                <Style TargetType="DataGridCell">
                    <Setter Property="IsEnabled" Value="{Binding Path=AutoScale}" />
                </Style>
            </DataGridTextColumn.CellStyle>
        </DataGridTextColumn>

輸出:

只讀

PS:以上解決方案1特定於您的代碼,因為“ Auto Scale column位於0 Index ,這就是為什么我在Binding使用Children[0]的原因。 如果有任何上下文需要,請更改。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM