2016-10-03 8 views
1

私は、(1)値を知りたい、(2)値が変更されたことを知りたいという意味で、200以上のプロパティを持つバイトデータに基づいたオブジェクトを持っています1つのメッセージから次のメッセージまで汎用オブジェクトプロパティに基づくWPF UserControl

私が使用していますXAMLのスニペット:現在

<Label Content="Prop Name" /> 
<TextBlock Text="{Binding PropName}" 
    Background="{Binding PropName, 
     Converter={StaticResource CompareToLastValueConverter}}" /> 

、私は適切なグリッド位置の設定と、各プロパティの貼り付けられたこれらの行を持っています。

私の質問はこれです:モデルから汎用オブジェクトのプロパティを取り、その後、値を割り当てる、ラベルに(スペースで)名前を割り当てて処理しネストされた WPFユーザーコントロールを作成するための良い方法があります上記の例のように、プロパティのTextBlockへの変換?

また、これはこの問題について考える最善の方法ですか、何かを行う「WPF方法」のリンクがありませんか?

答えて

1

私はしばしばこれを試してみたかった。 PropertyInfoのItemsControlテンプレートを作成します。

私は、テストクラスを作成:のプロパティを表示するには

public class MyClass 
    { 
     public string PropertyTest1 {get;set;} 
     public string PropertyTest2 { get; set; } 
     public string PropertyTest3 { get; set; } 
     public string PropertyTest4 { get; set; } 
    } 

を。私のデータコンテクストでは、私はバインドする2つのことがあります。 PropertyInfoのリストと問題のオブジェクト。 PropertyInfoが静的であるので、あなたがプロパティにバインドする必要がコンバータか何かを使用して、このより良い方法を行うことができる、としない場合があります:今

public PropertyInfo[] Properties 
    { 
     get { return typeof(MyClass).GetProperties(); } 
    } 

    public MyClass MyObject 
    { 
     get { return new MyClass { PropertyTest1 = "test", PropertyTest3 = "Some string", PropertyTest4 = "Last Property" }; } 
    } 

、プロパティを表示するのは簡単です:

<ItemsControl x:Name="PropertyDisplay" ItemsSource="{Binding Properties}" Grid.IsSharedSizeScope="True"> 
    <ItemsControl.Resources> 
     <local:PropertyInfoValueConverter x:Key="PropertyInfoValueConverter"/> 
    </ItemsControl.Resources> 
    <ItemsControl.ItemTemplate> 
     <DataTemplate> 
      <Grid> 
       <Grid.ColumnDefinitions> 
        <ColumnDefinition Width="Auto"/> 
        <ColumnDefinition Width="*"/> 
       </Grid.ColumnDefinitions> 
       <TextBlock Text="{Binding Name}" Margin="4,2"/> 
       <TextBlock Grid.Column="1" Margin="4,2"/> 
      </Grid> 
     </DataTemplate> 
    </ItemsControl.ItemTemplate> 
</ItemsControl> 

これらは「静的」なので、値にバインドすることはできません。それを回避する方法は、Tagプロパティを使用することで、マルチバインディングコンバーター:

だから、私たちのItemsSourceにTag="{Binding MyObject}"を追加し、私たちの第二のTextBlockの値コンバータにそのとPropertyInfoを投げることができます

0:これが結果です

public class PropertyInfoValueConverter : IMultiValueConverter 
{ 
    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) 
    { 
     PropertyInfo propertyInfo = values[0] as PropertyInfo; 
     return propertyInfo.GetValue(values[1]); 
    } 

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

   <TextBlock Grid.Column="1" Margin="4,2"> 
        <TextBlock.Text> 
         <MultiBinding Converter="{StaticResource PropertyInfoValueConverter}"> 
          <Binding Path=""/> 
          <Binding ElementName="PropertyDisplay" Path="Tag"/> 
         </MultiBinding> 
        </TextBlock.Text> 
       </TextBlock> 

コンバータを使用すると、(これだけ読み取り専用の方向に行く)テキストボックスを使用していない、特に以来、実際にはかなり簡単です

enter image description here

あなたは、いくつかのロジックはあなたが(大文字の前にスペース?)持っているものは何でも命名規則を探していると、コンバータで行うことができる名前、用のスペースが欲しいと言います。

テンプレートセレクタを使用してブール値、文字列、浮動小数点数のテンプレートを選択し、それらを別々に扱うのは楽しいことです。 (チェックボックス、テキスト、00。00形式のテキストなど)

編集:テンプレートセレクタ

を探るには、ここではサンプルテンプレートセレクタです:

public class PropertyInfoTemplateSelector : DataTemplateSelector 
{ 
    public DataTemplate StringTemplate { get; set; } 
    public DataTemplate IntegerTemplate { get; set; } 
    public DataTemplate DecimalTemplate { get; set; } 
    public DataTemplate BooleanTemplate { get; set; } 
    public DataTemplate DefaultTemplate { get; set; } 

    public override DataTemplate SelectTemplate(object item, DependencyObject container) 
    { 
     PropertyInfo propertyInfo = item as PropertyInfo; 
     if (propertyInfo.PropertyType == typeof(string)) 
     { 
      return StringTemplate; 
     } 
     else if (propertyInfo.PropertyType == typeof(int)) 
     { 
      return IntegerTemplate; 
     } 
     else if (propertyInfo.PropertyType == typeof(float) || propertyInfo.PropertyType == typeof(double)) 
     { 
      return DecimalTemplate; 
     } 
     else if (propertyInfo.PropertyType == typeof(bool)) 
     { 
      return BooleanTemplate; 
     } 
     return DefaultTemplate; 
    } 
} 

当社のItemsControlには、単に以下のようになります。

<ItemsControl x:Name="PropertyDisplay" ItemsSource="{Binding Properties}" 
       Grid.IsSharedSizeScope="True" 
       Tag="{Binding MyObject}" 
       ItemTemplateSelector="{StaticResource PropertyInfoTemplateSelector}" 
       Margin="20"/> 

私もスペースを追加しましたこのコンバーターを使用している名前で:

public class PropertyInfoNameConverter : IValueConverter 
{ 
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     string text = value as string; 
     if (string.IsNullOrWhiteSpace(text)) 
      return string.Empty; 
     StringBuilder newText = new StringBuilder(text.Length * 2); 
     newText.Append(text[0]); 
     for (int i = 1; i < text.Length; i++) 
     { 
      if (char.IsUpper(text[i])) 
       if ((text[i - 1] != ' ' && !char.IsUpper(text[i - 1])) || 
        (char.IsUpper(text[i - 1]) && 
        i < text.Length - 1 && !char.IsUpper(text[i + 1]))) 
        newText.Append(' '); 
      newText.Append(text[i]); 
     } 
     return newText.ToString(); 
    } 

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

(これに相当する:https://stackoverflow.com/a/272929/1305699)。

いくつかのboolean値を含むように私たちのクラスを更新し、フィールドFLOAD:

enter image description here

+0

非常に素晴らしいです!ありがとう。 – tjcertified

関連する問題