WPF MVVM ComboBox SelectedItem или SelectedValue не работает - PullRequest
40 голосов
/ 19 марта 2009

Обновление

После небольшого расследования. Проблема, по-видимому, заключается в том, что SelectedValue / SelectedItem происходит до завершения загрузки элемента Item. Если я сижу в точке останова и жду несколько секунд, она работает как положено. Не знаю, как я собираюсь обойти это.

Окончание обновления

У меня есть приложение, использующее в WPF MVVM с ComboBox. Ниже приведен пример ViewModel. У меня проблема в том, что когда мы покидаем нашу страницу и возвращаемся назад, ComboBox не выбирает выбранное текущее значение.

Просмотр модели

public class MyViewModel
{
     private MyObject _selectedObject;
     private Collection<Object2> _objects;
     private IModel _model;

     public MyViewModel(IModel model)
    {
         _model = model;
         _objects = _model.GetObjects();
    }

    public Collection<MyObject> Objects
    {
         get
         {
              return _objects;
         }
         private set
         {
              _objects = value;
         }
     }

     public MyObject SelectedObject
     {
          get
          {
              return _selectedObject;
          }
          set
          {
               _selectedObject = value;
          }
      }
 }

Для примера расскажем, что MyObject имеет два свойства (Text и Id). Мой XAML для ComboBox выглядит следующим образом.

1020 * XAML *

<ComboBox Name="MyComboBox" Height="23"  Width="auto" 
    SelectedItem="{Binding Path=SelectedObject,Mode=TwoWay}" 
    ItemsSource="{Binding Objects}"
    DisplayMemberPath="Text"
    SelectedValuePath="Id">

Независимо от того, каким образом я настраиваю это, когда я возвращаюсь на страницу и объект повторно собирается, ComboBox не будет выбирать значение. Объект возвращает правильный объект через свойство get в свойстве.

Я не уверен, является ли это просто проблемой способа работы шаблонов ComboBox и MVVM. Привязка текстового поля, которую мы делаем, работает правильно.

Ответы [ 17 ]

1 голос
/ 21 апреля 2011

Типы SelectedValuePath и SelectedValue должны быть ТОЧНО одинаковыми.

Если, например, тип SelectedValuePath равен Int16, а тип свойства, связанного с SelectedValue, равен int, он не будет работать.

Я трачу часы, чтобы найти это, и именно поэтому я отвечаю здесь после стольких времени, когда был задан вопрос. Может быть, другой бедный парень, как я, с той же проблемой, может увидеть это.

1 голос
/ 17 августа 2014

Я решил проблему, добавив диспетчер в событие UserControl_Loaded

 Dispatcher.BeginInvoke(DispatcherPriority.Loaded, new Action(() =>
 {
     combobox.SelectedIndex = 0;
 }));
1 голос
/ 11 января 2012

У меня была эта проблема с ComboBox отображением списка цветов (List ).
Выбор цвета был возможен, но он не отображался при закрытии выделения (хотя свойство было изменено!)

Исправление переписывало метод Equals (object obj) для типа, выбранного в ComboBox (Brush), который не был простым, потому что Brush запечатан. Поэтому я написал класс EqualityBrush , содержащий Brush и реализующий Equals:

public class EqualityBrush
{
    public SolidColorBrush Brush { get; set; }

    public override bool Equals(object o)
    {
        if (o is EqualityBrush)
        {
            SolidColorBrush b = ((EqualityBrush)o).Brush;
            return b.Color.R == this.Brush.Color.R && b.Color.G == this.Brush.Color.G && b.Color.B == this.Brush.Color.B;
        }
        else
            return false;
    }
}

Использование списка моего нового класса EqualityBrush вместо обычного класса Brush устранило проблему!

Мой комбинированный список XAML выглядит так:

<ComboBox ItemsSource="{Binding BuerkertBrushes}" SelectedItem="{Binding Brush, Mode=TwoWay}" Width="40">
    <ComboBox.Resources>
        <DataTemplate DataType="{x:Type tree:EqualityBrush}">
            <Rectangle Width="20" Height="12" Fill="{Binding Brush}"/>
        </DataTemplate>
    </ComboBox.Resources>
</ComboBox>

Помните, что мое свойство "Brush" в ViewModel теперь должно иметь тип EqualityBrush!

0 голосов
/ 01 февраля 2011

Использовать загруженное событие:

private void cmb_Loaded(object sender, RoutedEventArgs e) {
    if (cmb.Items.Count > 0) cmb.SelectedIndex = 0;          
}

Это работает для меня.

0 голосов
/ 21 марта 2009

Это может быть способ применения DataContext к странице. В WPF каждый раз, когда вы переходите на страницу, все переинициализируется, вызывается конструктор, загружаются методы, все. таким образом, если вы устанавливаете свой DataContext внутри вашего View, вы, несомненно, будете выбрасывать тот SelectedItem, который выбрал пользователь. Чтобы избежать этого, используйте свойство KeepAlive ваших страниц.

<Page KeepAlive="True" ...>
   ...
</Page>

Это приведет к запуску только события Loaded при переходе назад на страницу, которую вы уже посетили. Поэтому вам нужно убедиться, что вы устанавливаете DataContext в Initialize (внешне или внутри конструктора), а не в Load.

Однако это будет работать только для этого экземпляра страницы. Если вы перейдете к новому экземпляру этой страницы, конструктор будет вызван снова.

0 голосов
/ 28 июня 2010

ComboBox.SelectionBoxItem.ToString ()

0 голосов
/ 08 декабря 2010

IsSyncronizedWithCurrent = False заставит его работать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...