簡體   English   中英

WPF動態綁定

[英]WPF Dynamic Binding

今天,我正在研究一個WPF UserControl來顯示一些變量的當前值。 我想知道是否有辦法在WPF中創建一個超級簡單的屬性網格。 問題出在下面的XAML的主角上。 如何將字符串綁定到具有ItemTemplate的屬性,就像我在下面設置的那樣? 為了更清楚,我可以將綁定嵌入到彼此中{Binding Path={Binding Value}}

這是班級:

public class Food
{
    public string Apple { get; set; }
    public string Orange { get; set; }
    public IEnumerable<KeyValuePair<string, string>> Fields
    {
        get
        {
            yield return new KeyValuePair<string, string>("Apple Label", "Apple");
            yield return new KeyValuePair<string, string>("Orange Label", "Orange");
        }
    }
}

這是XAML:

<UserControl x:Class="MAAD.Plugins.FRACTIL.Simulation.SimulationStateView"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Height="331" Width="553">
 <ListView ItemSource="{Binding Fields}">
  <ListView.ItemTemplate>
   <DataTemplate>
    <StackPanel Orientation="Horizontal">
     <TextBlock Text="{Binding Key}" />
     **<TextBlock Text="{Binding Path={Binding Value}}" />**
    </StackPanel>
   </DataTemplate>
  </ListView.ItemTemplate>
 </ListView>
</UserControl>

問題的實質是您不僅需要字段描述和名稱列表,還需要具有這些字段和名稱的實際對象。

您可以使用像這樣的轉換器向字段對象添加目標引用,並提供值訪問器,如下所示:

  public class PropertyValueAccessConverter : IMultiValueConverter
  {
    object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
    {
      var target = values[0];
      var fieldList = values[1] as IEnumerable<KeyValuePair<string,string>>;
      return
        from pair in fieldList
        select new PropertyAccessor
        {
          Name = pair.Name,
          Target = target,
          Value = target.GetType().GetProperty(target.Value),
        };
    }

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

    public class PropertyAccessor
    {
      public string Name
      public object Target;
      public PropertyInfo Property;

      public object Value
      {
        get { return Property.GetValue(Target, null); }
        set { Property.SetValue(Target, value, null); }
      }
    }

    public static PropertyValueAccessConverter Instance = new PropertyValueAccessConverter();
  }

使用此轉換器,您可以像這樣綁定ItemsSource:

  <ListView>
    <ListView.ItemsSource>
      <MultiBinding Converter="{x:Static local:PropertyValueAccessConverter.Instance}">
        <Binding />
        <Binding Path="Fields" />
      </MultiBinding>
    </ListView.ItemsSource>
  </ListView>

順便說一下,實現Fields屬性的一種更有效的方法是:

  public IEnumerable<KeyValuePair<string, string>> Fields
  {
    get
    {
      return new KeyValuePair<string, string>[]
      {
        new KeyValuePair<string, string>("Apple Label", "Apple");
        new KeyValuePair<string, string>("Orange Label", "Orange");
      }
    }
  }

雖然坦率地說我會在各個屬性上使用描述屬性以及反射而不是對列表進行硬編碼。 這也將首先消除對MultiBinding的需求。

好吧,它應該只是:

<TextBlock Text="{Binding Path=Value}" />

但是,我想我明白你要做的是什么。 問題是KeyValuePair不是一個INotifyPropertyChange子類型(理所當然,不會進入那個)所以如果在字典中更改了值,你將永遠不會收到通知。 此外,KeyValuePair實際上是一個結構。 因此,更改綁定副本上的值不會更新實際數據源,因為它是數據的副本。

如果您正在使用的模型實際上是KeyValuePair,則需要創建更具體的View-Model類來啟用此數據綁定方案。 這需要是一種包裝Key的類,並且對底層源(可能是Dictionary?)有一個引用,並實際調用在其屬性發生更改時更新底層源的值。 也就是說,您仍然不會從字典中獲取通知(再次,假設這是您的來源),因為它不會觸發任何通知,因此您將無法提供轉發通知。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM