2012-07-14 14 views
9

Mam dziwny problem w mojej aplikacji Metro WinRT/C# XAML, korzystając z podglądu wydania Windows 8 (ostatnie zainstalowane poprawki). Używam ComboBox, którego wartości ItemsSource i SelectedValue są zobowiązane do właściwości w ViewModel:Parametr ComboBox SelectedValue nie wyświetla się

<ComboBox SelectedValue="{Binding MySelectedValue, Mode=TwoWay}" 
      ItemsSource="{Binding MyItemsSource, Mode=OneWay}" 
      Width="200" Height="30" /> 

Kod tyle:

public MainPage() 
{ 
    this.InitializeComponent(); 

    DataContext = new TestViewModel(); 
} 

I bardzo prosta definicja z TestViewModel, używając ciągi:

public class TestViewModel : INotifyPropertyChanged 
{ 
    public event PropertyChangedEventHandler PropertyChanged; 

    private IEnumerable<string> _myItemsSource = new List<string> 
     { 
      "Test Item 1", 
      "Test Item 2", 
      "Test Item 3" 
     }; 
    public IEnumerable<string> MyItemsSource 
    { 
     get { return _myItemsSource; } 
    } 

    private string _mySelectedValue = "Test Item 2"; 
    public string MySelectedValue 
    { 
     get { return _mySelectedValue; } 
     set 
     { 
      _mySelectedValue = value; 
      if (PropertyChanged != null) 
      { 
       PropertyChanged(this, new PropertyChangedEventArgs("MySelectedValue")); 
      } 
     } 
    } 
} 

Teraz myślałem, że to proste rozwiązanie powinno po prostu działać ... Ale kiedy uruchamiam aplikację, SelectedValue="Test Item 2" się nie wyświetla, ComboBox jest puste. Ustawiając punkty przerwania, zauważyłem, że powiązane wartości MyItemsSource i MySelectedValue są poprawne pobierane z modelu widoku, gdy ustawiam DataContext widoku. Po wykonaniu tej czynności właściwość ComboBox.SelectedValue jest ustawiona na "Test Item 2", ale po prostu się nie wyświetla! Zauważyłem również, że po zmianie wybranej wartości w ComboBox przez działanie użytkownika w interfejsie użytkownika zmieniona wartość pojawia się w ComboBox, a właściwość Model widoku jest odpowiednio aktualizowana. Tak więc wszystko wydaje się działać dobrze, z wyjątkiem początkowej wizualizacji właściwości modelu widoku MySelectedValue. Jestem teraz bardzo zdesperowany ...

Teraz, gdy jest to najprostszy przykład, w punkcie początkowym chciałem powiązać całe jednostki z ComboBox, ustawiając DisplayMemberPath i SelectedValuePath. Niestety, ten sam problem występuje.

+0

czy to dla ciebie praca? –

+0

Czy problem występuje nadal, jeśli otrzymujesz rzeczywisty element z kolekcji, zamiast przypisywać "nowy ciąg" do wybranej wartości, jak w "selectedValue = itemsSource [1]"? – Patrick

Odpowiedz

29

znalazłem problem w moim przykładzie: W znaczników XAML mam zdefiniowaną właściwość SelectedValueprzed właściwość ItemsSource. Jeśli mogę zamienić obie definicje w ten sposób to działa:

<ComboBox ItemsSource="{Binding MyItemsSource, Mode=OneWay}" 
     SelectedValue="{Binding MySelectedValue, Mode=TwoWay}" 
     Width="200" Height="30" /> 

To jest naprawdę dziwne i denerwujące. Teraz chciałbym wiedzieć: czy to błąd, czy projekt? Myślę, że to błąd, ponieważ kontrola powinna działać bez względu na kolejność zdefiniowanych właściwości w XAML.

+0

to było od Silverlight 2. –

+0

Dzięki za cynk. Używam Silverlight/WPF/Windows8 od lat i nigdy nie zauważyłem kolejności związania spraw. Ostatnio natknąłem się na ten problem podczas rozwijania aplikacji Windows8, zajęło mi trochę czasu, aby zdać sobie sprawę, że 'SelectedValue' było przed powiązaniem' ItemsSource'. –

+0

naprawdę? Nie sądziłem, że to ma znaczenie –

2

to rozwiązanie działa: można tu znaleźć https://skydrive.live.com/?cid=b55690d11b67401d&resid=B55690D11B67401D!209&id=B55690D11B67401D!209

<ComboBox Width="300" Height="32" HorizontalAlignment="Left" DisplayMemberPath="Name" 
        VerticalAlignment="Top" ItemsSource="{Binding PersonCollection}" 
        SelectedItem="{Binding SelectedPerson, Mode=TwoWay}"></ComboBox> 

ViewModle klasa jest

public class ViewModel:BaseViewModel 
    { 
     private Person selectedPerson; 
     public Person SelectedPerson { 
      get { return this.selectedPerson; } 
      set { this.selectedPerson = value; 
      this.RaisePropertyChanged("SelectedPerson"); 
      } 
     } 
     public ObservableCollection<Person> PersonCollection { get; set; } 

     public ViewModel() 
     { 
      this.PersonCollection = new ObservableCollection<Person>(); 
      this.PopulateCollection(); 

      //setting first item as default one 
      this.SelectedPerson = this.PersonCollection.FirstOrDefault(); 
     } 

     private void PopulateCollection() 
     { 
      this.PersonCollection.Add(new Person { Name="Oscar", Email="[email protected]" }); 
      this.PersonCollection.Add(new Person { Name = "Jay", Email = "[email protected]" }); 
      this.PersonCollection.Add(new Person { Name = "Viral", Email = "[email protected]" }); 
     } 
    }