none
WPF: DataGrid, привязка IsReadOnly к свойству элемента коллекции RRS feed

  • Вопрос

  • <DataGrid Name="BetsGrid" ItemsSource="{Binding}" AutoGenerateColumns="False" VerticalScrollBarVisibility="Visible" MaxHeight="200">
     <DataGrid.Columns>
      <DataGridCheckBoxColumn Header="Вкл" Binding="{Binding Path=active}" />
      <DataGridTextColumn Header="Счёт" Binding="{Binding Path=result}" 
    IsReadOnly="{Binding Path=active, Converter={StaticResource InverseBoolConverter}, Mode=OneWay}"/> <DataGridTemplateColumn Header="Min/Max коэф ЗА" CellEditingTemplate="{StaticResource MinMaxDiffBet}" CellTemplate="{StaticResource MinMaxDiffBet}"
    IsReadOnly
    ="{Binding Path=active, Mode=OneWay, Converter={StaticResource InverseBoolConverter}}"/> <DataGridTemplateColumn Header="Против" CellEditingTemplate="{StaticResource BetBParamSet}" CellTemplate="{StaticResource BetParamView}"/> </DataGrid.Columns> </DataGrid>
    <converter:InverseBoolConverter x:Key="InverseBoolConverter" />
    
    class InverseBoolConverter : IValueConverter
     {
      #region IValueConverter Members
      public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
      {
       if (value is bool)
        return !(bool)value;
       else
        throw new NotSupportedException();
      }
      public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
      {
       throw new NotSupportedException();
      }
      #endregion 
     }
    


    Хотелось бы привязать IsReadOnly столбцов DataGrid к свойству элемента коллекции.Для этого воспользовался конвертером, который должен вернуть противоположное значение этого свойства. Но почему то не получилось. В чём может быть проблема?


    15 июля 2011 г. 4:27

Ответы

  • Судя по всему, при помощи свойства isReadOnly у столбца DataGrid можно задать значение только сразу для всего столбца. Т.е. с его помощью нельзя сделать "только для чтения" одну или несколько ячеек в данном столбце.

    Как вариант решения - использовать DataGridTemplatedColumn. Объявить шаблон:

    <DataTemplate x:Key="TextColumnTemplate">
       <TextBox Text="{Binding Result}" IsReadOnly="{Binding Active, Converter={StaticResource InverseBoolConverter}}"/>
    </DataTemplate>
    

    и таким способом определить datagrid:

    <DataGrid Name="BetsGrid" AutoGenerateColumns="False" VerticalScrollBarVisibility="Visible" MaxHeight="200">
      <DataGrid.Columns>
        <DataGridCheckBoxColumn Header="Вкл" Binding="{Binding Path=Active, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
        <DataGridTemplateColumn Header="Счёт" CellTemplate="{StaticResource TextColumnTemplate}"/>
        <DataGridTemplateColumn Header="Min/Max коэф ЗА" />
        <DataGridTemplateColumn Header="Против" />
      </DataGrid.Columns>
    </DataGrid>
    

    Т.е. связь будет происходить за счёт свойства Active (как вы видимо и задумывали изначально). Меняя его в 1й колонке, посредством binding разрешаем\запрещаем редактирование 2й колонки.

    Ещё существенный момент - я указал в Binding для колонки с checkbox:

    1) Mode=TwoWay - чтобы при изменении флажка менялось свойство у сущности из коллекции ItemsSource

    2) UpdateSourceTrigger=PropertyChanged - чтобы изменение свойство происходило сразу же при изменении состояния checkbox

    • Предложено в качестве ответа Vitaly Dilmukhametov 19 июля 2011 г. 16:14
    • Помечено в качестве ответа Abolmasov Dmitry 22 июля 2011 г. 10:48
    19 июля 2011 г. 16:13

Все ответы

  • Здравствуйте

    Посмотрите ошибки биндинга во время запуска и работы приложения в окне Output в Visual Studio. Возможно не находится сам конвертор, т.к. он определен после использования. Попробуйте перенести определение конвертора вверх, до определения DataGrid.


    Для связи [mail]
    15 июля 2011 г. 6:07
  • Хмс ... мой код в сообщении малость в заблуждение ввёл. Конвертор определён в рсурсах. И соответственно он стоит выше, чем DataGrid.

     

    Вот ошибку какую выдаёт:

    System.Windows.Data Error: 2 : Cannot find governing FrameworkElement or FrameworkContentElement for target element. BindingExpression:Path=active; DataItem=null; target element is 'DataGridTextColumn' (HashCode=36877180); target property is 'IsReadOnly' (type 'Boolean')
    System.Windows.Data Error: 2 : Cannot find governing FrameworkElement or FrameworkContentElement for target element. BindingExpression:Path=active; DataItem=null; target element is 'DataGridTemplateColumn' (HashCode=52226756); target property is 'IsReadOnly' (type 'Boolean')

    Похоже это из-за того, что когда происходит конструирование страницы, коллекция, которую необходимо отобразить, ещё не существует. Соответственно и возникает ошибка и не происходит привязка.

    Как тогда реализовать такой момент:

    Пока не стоит галочка "Вкл" в первом столбце, остальные столбцы запретить для редактирования?


    15 июля 2011 г. 6:17
  • На правах UP'а
    19 июля 2011 г. 12:37
  • Судя по всему, при помощи свойства isReadOnly у столбца DataGrid можно задать значение только сразу для всего столбца. Т.е. с его помощью нельзя сделать "только для чтения" одну или несколько ячеек в данном столбце.

    Как вариант решения - использовать DataGridTemplatedColumn. Объявить шаблон:

    <DataTemplate x:Key="TextColumnTemplate">
       <TextBox Text="{Binding Result}" IsReadOnly="{Binding Active, Converter={StaticResource InverseBoolConverter}}"/>
    </DataTemplate>
    

    и таким способом определить datagrid:

    <DataGrid Name="BetsGrid" AutoGenerateColumns="False" VerticalScrollBarVisibility="Visible" MaxHeight="200">
      <DataGrid.Columns>
        <DataGridCheckBoxColumn Header="Вкл" Binding="{Binding Path=Active, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
        <DataGridTemplateColumn Header="Счёт" CellTemplate="{StaticResource TextColumnTemplate}"/>
        <DataGridTemplateColumn Header="Min/Max коэф ЗА" />
        <DataGridTemplateColumn Header="Против" />
      </DataGrid.Columns>
    </DataGrid>
    

    Т.е. связь будет происходить за счёт свойства Active (как вы видимо и задумывали изначально). Меняя его в 1й колонке, посредством binding разрешаем\запрещаем редактирование 2й колонки.

    Ещё существенный момент - я указал в Binding для колонки с checkbox:

    1) Mode=TwoWay - чтобы при изменении флажка менялось свойство у сущности из коллекции ItemsSource

    2) UpdateSourceTrigger=PropertyChanged - чтобы изменение свойство происходило сразу же при изменении состояния checkbox

    • Предложено в качестве ответа Vitaly Dilmukhametov 19 июля 2011 г. 16:14
    • Помечено в качестве ответа Abolmasov Dmitry 22 июля 2011 г. 10:48
    19 июля 2011 г. 16:13
  • Mode=TwoWay - на сколько я могу судить не обязательно, так как этот режим по умолчанию.

     

    В остальном попробую как Вы предложили сделать. Благодарю за ответ.

    20 июля 2011 г. 4:46