2

WPF DataGridを使用して、セルオブジェクトプロパティの関連する値に基づいて、DataGridCellのさまざまな表示および関連するプロパティ(Foreground、FontStyle、IsEnabledなど)を変更する必要があります。

これは、たとえば(ObservableDictionariesのObservableコレクションを使用して)コードで簡単に実行できます。

  var b = new Binding("IsLocked") { Source = row[column], Converter = new BoolToFontStyleConverter() };
  cell.SetBinding(Control.FontStyleProperty, b);

正常に動作しますが、セルオブジェクトのプロパティにパスを設定する方法が見つからないため、XAMLでこれを行う方法がわかりません。

XAMLの試みの1つは次のとおりです。

<Setter Property="FontStyle">
    <Setter.Value>
        <MultiBinding Converter="{StaticResource IsLockedToFontStyleConverter}" Mode="OneWay" UpdateSourceTrigger="PropertyChanged">
              <Binding />
              <Binding RelativeSource="{x:Static RelativeSource.Self}"/>
        </MultiBinding>
    </Setter.Value>
</Setter>

ただし、IsLockedプロパティへのバインドはありません

public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
    var row = (RowViewModel) values[0];
    var cell = (DataGridCell) values[1];
    if (cell != null && row != null)
    {
        var column = DataGridMethods.GetColumn(cell);
        return row[column].IsLocked ? "Italic" : "Normal";
    }

    return DependencyProperty.UnsetValue;
}

以前のバージョンはrow[col].IsLockedを返し、DataTriggerを使用してFontStyleを設定しましたが、返されたオブジェクトはデータバインドされていないことに注意してください。

もちろん、アプリケーションは設計時に列が何であるかを認識していないことに注意してください。

最後に、DataTableは私の要件にはあまりにも非効率的ですが、とにかくDataTableでこれがどのように行われるかを確認したいと思います。そのようなソリューションがあれば、他の場所で役立つ可能性があります(ただし、コレクションを使用することをお勧めします)。

確かにこれは一般的な問題であり、私はプロジェクトですべてのMVVMを実行しようとしているWPF初心者ですが、この問題はWPFDataGridの使用に関して私を妨げています。

4

1 に答える 1

4

これが私が見つけた最も簡単な解決策です。(実際、この質問や他の質問を投稿する前に持っていましたが、そのような解決策には恥ずかしかったです。ここでは他に何も聞いたことがなく、他の誰かが同じ問題に直面した場合に備えて、共有したいと思いました。)

セルオブジェクトへの参照をDataGridCellタグプロパティに配置します。これは、XAMLとコンバーター内のコードバインディングを組み合わせて次のように行います。

   <Setter Property="Tag">
       <Setter.Value>
           <MultiBinding Converter="{StaticResource CellViewModelToTagConverter}" Mode="OneWay" UpdateSourceTrigger="PropertyChanged">
              <Binding />
              <Binding RelativeSource="{x:Static RelativeSource.Self}"/>
          </MultiBinding>
       </Setter.Value>
   </Setter>

 public class CellViewModelToTagConverter : IMultiValueConverter
 {
     public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
     {
        var row = values[0] as RowViewModel;
        var cell = values[1] as DataGridCell;
        if (row != null && cell != null)
        {
            var column = DataGridMethods.GetColumn(cell);
            // hack within hack!!! (using tag way is itself a hack?)
            var b = new Binding("Self") {Source = row[column]};
            cell.SetBinding(FrameworkElement.TagProperty, b);
            //...
            //return row[column];
            return DependencyProperty.UnsetValue;
        }
        return DependencyProperty.UnsetValue;
    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
    {
        throw new NotSupportedException();
    }
}

コンバーター内のコメントから、このソリューションについて私がどう思うかがわかります(CellオブジェクトにSelfプロパティを追加し、コンストラクターでSelf = thisを作成する必要がありました)。

それでも、Datagridコーディングを完全にMVVMにすることができます-コンバーター内で行ったことはMVVMと一致していることを認めれば。とにかくそれは動作します!

したがって、このようにすることで、関連する列セルスタイル内にXAMLを配置することで(DataGrid.CellStyleを介してこれを行わない)、特定の列でのみそのようなバインディングを制御するなど、XAMLからすべてを表示および管理できます。

とにかく、使用例は

<Style.Triggers>
      <DataTrigger Value="true" Binding="{Binding RelativeSource={RelativeSource Self}, Path=Tag.IsLocked}">
            <Setter Property="FontStyle" Value="Italic"/>
            <Setter Property="IsEnabled" Value="False"/>
       </DataTrigger>
 </Style.Triggers>

XAMLレベルでは、シンプルでIMHOエレガントです(特に、セルオブジェクトのプロパティを多用するさまざまなツールチップやポップアップの場合)。しかし、これを行うためのより良い方法があると確信していますね。

Net 4.0と動的オブジェクトを使用できるようになると、これがすべてなくなることを願っていますが、このプロジェクトでは使用できません。

于 2010-09-05T11:11:22.937 に答える