2017-08-02 55 views
0

我有一個組合框,並希望將其ItemsSource綁定到IEnumerable<(string,string)>。如果我沒有設置DisplayMemberPath,那麼它將起作用,並在下拉區域顯示在項目中調用ToString()的結果。不過,當我設置DisplayMemberPath="Item1"它不再顯示任何東西。我做了以下示例,其中您可能會看到如果使用經典Tuple類型,則按預期工作。ValueTuple不支持DisplayMemberPath。組合框,WPF

在調試時,我已經檢查到valuetuple的Item1和Item2也是屬性。

我的XAML:

<Window x:Class="TupleBindingTest.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     Loaded="MainWindow_OnLoaded" 
     Title="MainWindow" Height="350" Width="525"> 
    <Grid> 
     <Grid.RowDefinitions> 
      <RowDefinition/> 
      <RowDefinition/> 
     </Grid.RowDefinitions> 

     <ComboBox x:Name="TupleCombo" Grid.Row="0" VerticalAlignment="Center" 
        DisplayMemberPath="Item1" /> 
     <ComboBox x:Name="ValueTupleCombo" Grid.Row="1" VerticalAlignment="Center" 
        DisplayMemberPath="Item1" /> 
    </Grid> 
</Window> 

而且我隱藏:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Windows; 

namespace TupleBindingTest 
{ 
    public partial class MainWindow 
    { 
     public MainWindow() 
     { 
      InitializeComponent(); 
     } 

     private IEnumerable<Tuple<string, string>> GetTupleData() 
     { 
      yield return Tuple.Create("displayItem1", "valueItem1"); 
      yield return Tuple.Create("displayItem2", "valueItem2"); 
      yield return Tuple.Create("displayItem3", "valueItem3"); 
     } 

     private IEnumerable<(string, string)> GetValueTupleData() 
     { 
      yield return ("displayItem1", "valueItem1"); 
      yield return ("displayItem2", "valueItem2"); 
      yield return ("displayItem3", "valueItem3"); 
     } 

     private void MainWindow_OnLoaded(object sender, RoutedEventArgs e) 
     { 
      TupleCombo.ItemsSource = GetTupleData(); 
      ValueTupleCombo.ItemsSource = GetValueTupleData(); 
     } 
    } 
} 

在運行這個樣本將正確顯示數據在第一組合框,但會什麼都不顯示在第二位。

爲什麼會發生這種情況?

回答

4

這是因爲DisplayMemberPath內部設置綁定與每個項目的模板指定的路徑。所以設置DisplayMemberPath="Item1"基本上是以下ComboBox.ItemTemplate簡寫設置:

<DataTemplate> 
    <ContentPresenter Content="{Binding Item1}" /> 
</DataTemplate> 

現在WPF只支持綁定屬性。這就是爲什麼當您使用Tuple s時它工作正常 - 因爲它的成員是屬性,以及爲什麼它不能與ValueTuple s一起使用 - 因爲它的成員是字段

你的具體情況雖然,因爲你用這些藏品僅作爲綁定源,你可以使用匿名類型來實現自己的目標(其成員也性質),例如:

private IEnumerable<object> GetTupleData() 
{ 
    yield return new { Label = "displayItem1", Value = "valueItem1" }; 
    yield return new { Label = "displayItem2", Value = "valueItem2" }; 
    yield return new { Label = "displayItem3", Value = "valueItem3" }; 
} 

然後,你可以設置你的ComboBox有:

<ComboBox DisplayMemberPath="Label" SelectedValuePath="Value" (...) /> 
+2

這個故事告訴我們,一個'ValueTuple'的項目被暴露領域,而不是性能,和WPF做不支持綁定到字段。 –