2010-06-07 5 views
4

Я использую MVVM (MVVM Light Toolkit) и имею свойство на модели представления, которое предоставляет список объектов. Объекты содержат два свойства, обе строки, которые коррелируют с аббревиатурой и описанием. Я хочу, чтобы ComboBox отображал спаривание как «аббревиатура - описание». Если я использую шаблон данных, он делает это легко.WPF ComboBox Связывание с нестроковым объектом

У меня есть другое свойство в модели представления, которое представляет объект, который должен отображаться как выбранный - выбранный элемент в ComboBox. Я привязываю ItemsSource к списку, поскольку он представляет юниверс доступных вариантов, и я пытаюсь привязать SelectedItem к этому объекту. Я убиваю себя, пытаясь понять, почему я не могу заставить его работать, и чувствовать себя скорее мошенничеством по часам.

Чтобы понять, почему это работает, я создал тот же подход, что и список строк, и выбранную строку. Это прекрасно работает. Значит, это явно связано с типизацией ... возможно, в выборе равенства? Или, возможно, это связано с шаблоном данных?

Вот XAML:

<Window x:Class="MvvmLight1.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     Title="MainWindow" 
     Height="300" 
     Width="300" 
     DataContext="{Binding Main, Source={StaticResource Locator}}"> 

    <Window.Resources> 
     <ResourceDictionary> 
      <ResourceDictionary.MergedDictionaries> 
       <ResourceDictionary Source="Skins/MainSkin.xaml" /> 
      </ResourceDictionary.MergedDictionaries> 
      <DataTemplate x:Key="DataTemplate1"> 
       <StackPanel Orientation="Horizontal"> 
        <TextBlock TextWrapping="Wrap" Text="{Binding CourtCode}"/> 
        <TextBlock TextWrapping="Wrap" Text=" - "/> 
        <TextBlock TextWrapping="Wrap" Text="{Binding CourtDescription}"/> 
       </StackPanel> 
      </DataTemplate> 
     </ResourceDictionary> 
    </Window.Resources> 

    <Grid x:Name="LayoutRoot"> 
     <ComboBox x:Name="cmbAbbrevDescriptions" Height="35" Margin="25,75,25,25" VerticalAlignment="Top" ItemsSource="{Binding Codes}" ItemTemplate="{DynamicResource DataTemplate1}" SelectedItem="{Binding selectedCode}" /> 
     <ComboBox x:Name="cmbStrings" Height="35" Margin="25" VerticalAlignment="Top" ItemsSource="{Binding strs}" SelectedItem="{Binding selectedStr}"/> 
    </Grid> 
</Window> 

И, если полезно, вот ViewModel:

using GalaSoft.MvvmLight; 
using MvvmLight1.Model; 
using System.Collections.Generic; 

namespace MvvmLight1.ViewModel 
{ 
    public class MainViewModel : ViewModelBase 
    { 
     public const string CodesPropertyName = "Codes"; 
     private List<Court> _codes = null; 
     public List<Court> Codes 
     { 
      get 
      { 
       return _codes; 
      } 

      set 
      { 
       if (_codes == value) 
       { 
        return; 
       } 

       var oldValue = _codes; 
       _codes = value; 

       // Update bindings and broadcast change using GalaSoft.Utility.Messenging 
       RaisePropertyChanged(CodesPropertyName, oldValue, value, true); 
      } 
     } 

     public const string selectedCodePropertyName = "selectedCode"; 
     private Court _selectedCode = null; 
     public Court selectedCode 
     { 
      get 
      { 
       return _selectedCode; 
      } 

      set 
      { 
       if (_selectedCode == value) 
       { 
        return; 
       } 

       var oldValue = _selectedCode; 
       _selectedCode = value; 

       // Update bindings and broadcast change using GalaSoft.Utility.Messenging 
       RaisePropertyChanged(selectedCodePropertyName, oldValue, value, true); 
      } 
     } 

     public const string strsPropertyName = "strs"; 
     private List<string> _strs = null; 
     public List<string> strs 
     { 
      get 
      { 
       return _strs; 
      } 

      set 
      { 
       if (_strs == value) 
       { 
        return; 
       } 

       var oldValue = _strs; 
       _strs = value; 

       // Update bindings and broadcast change using GalaSoft.Utility.Messenging 
       RaisePropertyChanged(strsPropertyName, oldValue, value, true); 
      } 
     } 

     public const string selectedStrPropertyName = "selectedStr"; 
     private string _selectedStr = ""; 
     public string selectedStr 
     { 
      get 
      { 
       return _selectedStr; 
      } 

      set 
      { 
       if (_selectedStr == value) 
       { 
        return; 
       } 

       var oldValue = _selectedStr; 
       _selectedStr = value; 

       // Update bindings and broadcast change using GalaSoft.Utility.Messenging 
       RaisePropertyChanged(selectedStrPropertyName, oldValue, value, true); 
      } 
     } 


     /// <summary> 
     /// Initializes a new instance of the MainViewModel class. 
     /// </summary> 
     public MainViewModel() 
     { 
      Codes = new List<Court>(); 

      Court code1 = new Court(); 
      code1.CourtCode = "ABC"; 
      code1.CourtDescription = "A Court"; 

      Court code2 = new Court(); 
      code2.CourtCode = "DEF"; 
      code2.CourtDescription = "Second Court"; 

      Codes.Add(code1); 
      Codes.Add(code2); 


      Court code3 = new Court(); 
      code3.CourtCode = "DEF"; 
      code3.CourtDescription = "Second Court"; 
      selectedCode = code3; 

      selectedStr = "Hello"; 
      strs = new List<string>(); 
      strs.Add("Goodbye"); 
      strs.Add("Hello"); 
      strs.Add("Ciao"); 

     } 
    } 
} 

А вот до смешного тривиальный класс, подвергаясь:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 

namespace MvvmLight1.Model 
{ 
    public class Court 
    { 
     public string CourtCode { get; set; } 

     public string CourtDescription { get; set; } 
    } 
} 

Спасибо!

ответ

1

Время выполнения не знает, что code2 и code3 должны быть равны.

см http://msdn.microsoft.com/en-us/library/ms173147(VS.80).aspx

public override bool Equals(object o) 
{ 
    var court = o as Court; 
    if(court == null) 
     return false; 
    return CourtCode == court.CourtCode; 
} 
+0

Удивительный! Это не имело никакого отношения к WPF, привязке и т. Д. Это была просто глупая ошибка в отношении равенства типов. Спасибо тонны! –

0

Ваш код SelectedCode3 отсутствует в коллекции Кодов. Добавьте его так, чтобы выбор работал так, как ожидалось.

Ваш selectedStr работает, потому что он находится в коллекции. [strs.Add("Hello");]

+0

или переопределить метод Equals в классе суда, помните также переопределить метод GetHashCode. – Oggy

+0

Право, code3 нет в коллекции Кодов. Но это эквивалентно code2 ... и вот где я пропадаю лодку. Я пытаюсь сказать «из всех этих возможных типов, выберите один тип, который соответствует этому». –

+0

@Oggy - Если я понимаю, вы говорите, что ComboBox пытается установить выбранный элемент, но он не может определить равенство между экземплярами объекта? –