2016-04-15 90 views
0

基本上,我有幾個列的DataGrid,我想啓用(改變IsReadOnly屬性)根據CheckBoxIsChecked一個DataGridTextColumn,位於同一DataGrid另一DataGridTemplateColumn綁定DataGridTextColumn的IsReadOnly到DataGridTemplateColumn複選框器isChecked

這裏(的重要組成部分)的代碼:

<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實現這一點,但我需要第一部分工作壽。

編輯:

回答一個很好的問題,我的目標是禁用鄰小區(同一行),而不是整個列。

+0

你想禁用整列或相鄰單元? –

+0

好點。答案將是相鄰的單元格。想想看,問題可能比我想象的更復雜。 –

+0

最簡單的解決方案是將AutoScale屬性綁定到Scale列的單元格樣式的IsEnable屬性。請看我的答案,我已經給出了依賴於UI和數據依賴的答案。 –

回答

2

使用下面爲您ScaleColumn結合:

<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> 

輸出:

ReadOnly

PS:上述方案1是針對你的代碼,導致Auto Scale columnIndex這就是爲什麼我在 Binding使用Children[0]。如果有任何上下文需求,請更改。

+1

解決方案2滿足了我的需求,簡單而乾淨。謝謝! –

+0

@ lucas.mdo是的,我會更喜歡相同:) –

2

這種類型的問題真的是Model-View-ViewModel (MVVM) pattern存在的原因。

使用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控制。

請注意,許多用於實現INotifyPropertyChanged的樣板可以使用庫/ NuGet包(如MVVM Light Toolkit和PropertyChanged.Fody)進行簡化。

+0

我確實使用了MVVM模式,而且我確實有兩個ViewModels您建議。儘管如此,我無法按照我想要的方式工作,也許是因爲我試圖避免在Scale中使用DataGridTemplateColumn。 –

相關問題