2017-07-06 1 views
0

私はユニークな状況があります。あるクラスでは、 "表示"クラスのように機能する内部クラスがあります。外部クラスには、内部クラスの型を返すGetDisplayObjectというメソッドがあります。WPF DataGrid、コンバーターでディスプレイをカスタマイズする

私は外部クラスでデータグリッドにバインドしようとしていますが、コンバーターを使用して正しい表示をしたいと思います。このようにして、私たちのアプリケーションでたくさんのコードを変更する必要はなく、いくつかの.xamlファイルにいくつかの行を追加するだけです。

私はそれが最も基本的なレベルで私の問題をかなり要約している小さなテストアプリケーションを作った。理想的には、私はSelectedItemを使用しているときに私はその特定のタイプに依存するコードのトンを変更する必要はありませんコンバータ(コンバータを使用し、値を返すことによって、問題を解決したいと思いますこの場合はDataObject型になります)。だからここ

ここ
using System.Collections.ObjectModel; 
using System.ComponentModel; 
using System.Windows; 

namespace TestApp 
{ 
public partial class MainWindow : Window, INotifyPropertyChanged 
{ 
    public MainWindow() 
    { 
     this.DataContext = this; 
     InitializeComponent(); 

     this.DataObjectCollection = new ObservableCollection<DataObject>(); 
     this.DataObjectCollection.Add(new DataObject() { Id = 1, Object1 = "this", Object2 = "that" }); 
     this.DataObjectCollection.Add(new DataObject() { Id = 1, Object2 = "that" }); 

     this.SelectedItem = new DataObject(); 
    } 

    private ObservableCollection<DataObject> dataObjectCollection; 
    private DataObject selectedItem; 

    public ObservableCollection<DataObject> DataObjectCollection 
    { 
     get { return this.dataObjectCollection; } 
     set 
     { 
      dataObjectCollection = value; 
      OnNotifyPropertyChanged("DataObjectCollection"); 
     } 
    } 

    public DataObject SelectedItem 
    { 
     get { return this.selectedItem; } 
     set 
     { 
      selectedItem = value; 
      OnNotifyPropertyChanged("SelectedItem"); 
     } 
    } 


    public event PropertyChangedEventHandler PropertyChanged; 
    private void OnNotifyPropertyChanged(string property = "") 
    { 
     if(PropertyChanged != null) 
     { 
      PropertyChanged(this, new PropertyChangedEventArgs(property)); 
     } 
    } 
} 
} 

はXAMLで後ろに私のXAMLの私がここ

namespace TestApp 
{ 
    public class DataObject 
    { 
     public class DataObjectDisplay 
     { 
      public string ObjectDisplay { get; set; } 
     } 

     // props 
     public int Id { get; set; } 
     public object Object1 { get; set; } 
     public object Object2 { get; set; } 

     // method for getting the display 
     public DataObjectDisplay GetDisplayObject() 
     { 
      DataObjectDisplay display = new DataObjectDisplay(); 

      // logic for determining which object should be displayed 
      if(Object1 == null) 
      { 
       display.ObjectDisplay = "Object1"; 
      } 
      else 
      { 
       display.ObjectDisplay = "Object2"; 
      } 
      return display; 
     } 
    } 
} 

にコードされて扱うこだわっているオブジェクトである(このようなものが何であるかを私はしたいですこのGetDisplay関数を呼び出すために、itemtemplateなどを使用してからコンバーターを使用してこのGetDisplay関数を呼び出す)、

<Window x:Class="TestApp.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:local="clr-namespace:TestApp" 
    mc:Ignorable="d" 
    Title="MainWindow" Height="350" Width="525"> 
<Window.Resources> 
    <local:DataObjectToDisplayDataObjectConverter x:Key="ToDisplayConverter"/> 
</Window.Resources> 
<StackPanel> 
    <DataGrid ItemsSource="{Binding DataObjectCollection}" SelectedItem="{Binding SelectedItem}" MinHeight="200"> 
     <DataGrid.ItemTemplate> 
      <DataTemplate> 
       <ContentPresenter Content="{Binding Converter={StaticResource ToDisplayConverter}}"/> 
      </DataTemplate> 
     </DataGrid.ItemTemplate> 
    </DataGrid> 
</StackPanel> 
</Window> 
210そして最終的にコンバータ

using System; 
using System.Globalization; 
using System.Windows.Data; 

namespace TestApp 
{ 
public class DataObjectToDisplayDataObjectConverter : IValueConverter 
{ 
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     if (value != null && value.GetType() == typeof(DataObject)) 
     { 
      DataObject dataObj = (DataObject)value; 
      dataObj.GetDisplayObject(); 
      return dataObj; 
     } 
     return "Invalid Value"; 
    } 

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     throw new NotImplementedException(); 
    } 
} 
} 

私は提案がありますが、これは小さな例です。私たちの実際のアプリケーションでは、1つのことはおそらく巨大な試練にカスケードするでしょう。

+0

ようになってしまった;' 'のInitializeComponent()の後;'。私はあなたがテストアプリケーションと他の場所のためのビューモデルとしてのみウィンドウを使用することを願っています。そして第二に、あなたの問題は何ですか?あなたはあなたのアプリのアーキテクチャについて説明しましたが、その問題は何ですか? 'value.GetType()== typeof(DataObject)'は使わないでください。 'is'と' as'演算子があります。 'DataGrid'に' ItemTemplate'を指定しないでください。セルのカスタムコンテンツが必要な場合は、列を指定し、それらに 'CellTemplate'を定義する必要があります。 – Maxim

+0

ええ、私はちょうどこれを一緒にすばやく投げて試してみて、状況に適切なコンテキストを提供しました。私の問題は、明確にするために、itemsSourceをDataObjectDisplayのコレクションに変更したくないということです。しかし、それが私がUI上で表現したがっているものです。 – Marsh

+0

はい、あなたは 'ItemsSource'を変更したくありません。しかし、あなたはすでに自分の仕事のための解決策を提供しています:コンバータ。あなたはこれがOKかどうか尋ねますか?これは実際の質問ですか? – Maxim

答えて

0

私があなただったら、ViewModelとのビューの密接な結合を変更しました。新しいMainWindowViewModelクラス&を作成するのと同じように、ViewModel内にすべてのプロパティを持つように変更しました。

GetDisplayObjectメソッドをもう1つ見てみましょう。コンバータからそのようなメソッドを呼び出す必要があります。

このコード&をこのようなものに変換すると、このコードを再調整することができます。幸いにも

public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 
{ 
    DataObject dataObj = value as DataObject; 

    if (value == null) 
    { 
     return "Invalid Value"; 
    } 

    if (dataObj.Object1 == null) 
    { 
     return "Object1"; 
    } 

    return "Object2"; 
} 
+0

私たちはMVVMパターンに従いますが、コードの後ろにテストアプリケーションを一緒に投げ込むのは簡単だと思いました。正直なところ、ロジックをコンバーターに移すことは悪い考えではないと思います。それは他のタイプのアプリケーションでも使用できるロジックなので、アプリケーションの下層にうまく収まります – Marsh

0

それは一つのオブジェクトがnullだったし、文字列が空で関連だ場合の問題だったので、私はDependencyProperty.UnsetValueを返し、次のバインディングを使用するように強制するコンバータとの結合の優先順位を使用することができました。私はこれがこの状況のた​​めの最善の解決策だと思う。

だから、xamlはこのようになりました。

<DataGrid ItemsSource="{Binding DataObjectCollection}" SelectedItem="{Binding SelectedItem}" MinHeight="200"> 
     <DataGrid.Columns> 
      <DataGridTemplateColumn> 
       <DataGridTemplateColumn.CellTemplate> 
        <DataTemplate> 
         <TextBlock> 
          <TextBlock.Text> 
           <PriorityBinding> 
            <Binding Path="Object1" Converter="{StaticResource EmptyStringToDependencyPropertyUnset}"/> 
            <Binding Path="Object2"/> 
           </PriorityBinding> 
          </TextBlock.Text> 
         </TextBlock> 
        </DataTemplate> 
       </DataGridTemplateColumn.CellTemplate> 
      </DataGridTemplateColumn> 
     </DataGrid.Columns> 
    </DataGrid> 

、コンバータは、すべての場所の最初に `this.DataContext =この本

public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     if(value == null || value as string == string.Empty) 
     { 
      return DependencyProperty.UnsetValue; 
     } 
     return value; 
    }