WPF ComboBox SelectedItem

Хорошо работа с WPF некоторое время, но я нуждаюсь в некоторой помощи.

У меня есть a ComboBox как ниже:

<TabControl>
    <TabItem Header="1">
        <ComboBox ItemsSource="{Binding MyList}" SelectedItem="{Binding MyListSelection}"/>
    </TabItem>
    <TabItem Header="2"/>
</TabControl>

Каждый раз, когда я переезжаю от вкладки 1 и затем возвращаюсь к ней, выбор удален. Я думаю, что причина этого состоит в том, что средства управления уничтожаются, когда они выходят из объема и затем обратно в. Но в процессе, из которого SelectedItem становится пустым, который не является действительно, что хотел пользователь, это - событие из-за жизненного цикла UI.

Таким образом, я задаюсь вопросом, что состоит в том, чтобы взять оптимальный маршрут? Я создаю это приложение с MVVM, таким образом, я мог проигнорировать вызов аппарата на Свойстве MyListSelection в моем ViewModel, но я имею ComboBoxes повсеместно и не люблю изменять свой ViewModel для того, что я рассматриваю ошибкой WPF.

Я мог разделить WPF ComboBox на подклассы, но нет никакого события SelectedItemChanging, я могу только добавить обработчик когда измененный SelectedItem.

Какие-либо идеи?

ОБНОВЛЕНИЕ:

Хорошо, после избиения моей головы против стены я узнал, почему моя проблема не могла быть воспроизведена. Если тип элемента списка является классом по некоторым причинам, SelectedItem установлен WPF на пустой указатель, но если это - тип значения, он не делает.

вот мой тестовый класс (VMBase является просто абстрактным классом, который реализует INotifyPropertyChanged):

public class TestListViewModel : VMBase
{
    public TestListViewModel()
    {
        TestList = new List<TestViewModel>();
        for (int i = 0; i < 10; i++)
        {
            TestList.Add(new TestViewModel(i.ToString()));
        }
    }

    public List<TestViewModel> TestList { get; set; }

    TestViewModel _SelectedTest;
    public TestViewModel SelectedTest
    {
        get { return _SelectedTest; }
        set
        {
            _SelectedTest = value;
            OnPropertyChanged("SelectedTest");
        }
    }
}

public class TestViewModel : VMBase
{
  public string Name {get;set;}
}

Таким образом, когда я изменяюсь, TestList, чтобы ввести интервал и пойти назад и вперед между вкладками SelectedItem остается таким же. Но когда это имеет тип TestViewModel SelectedTest устанавливается в NULL, когда tabitem идет не в фокусе.

Что продолжается?

7
задан Nathan 29 August 2012 в 16:05
поделиться

5 ответов

У меня точно такая же проблема, и до сих пор я не мог понять, в чем проблема. Я тестировал на 4 разных машинах с одной и той же ОС, версией .Net и аппаратными характеристиками и смог воспроизвести проблему на двух из них, на других работал нормально. Временное решение, которое я смог найти, работает для меня: для определения привязки SelectedItem перед ItemsSource. Как ни странно, если я следую этому шаблону, все работает так, как ожидалось. Тем не менее, вам просто нужно сделать следующее:

<Window x:Class="ComboBoxInTabItemSpike.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="300" Width="300">
    <StackPanel>
        <TabControl>
            <TabItem Header="1">
                <ComboBox SelectedItem="{Binding MySelect}" ItemsSource="{Binding MyList}"/>
            </TabItem>
            <TabItem Header="2"/>
        </TabControl>
        <TextBlock Text="{Binding MySelect}"/>
    </StackPanel>
</Window>
10
ответ дан 7 December 2019 в 01:21
поделиться

Я бы порекомендовал проверить привязки. Если что-то еще в вашем приложении меняется выбранный элемент или источник элементов, то ваше привязка сломается. Вы также можете посмотреть в Visual Studio в окне вывода, чтобы увидеть, есть ли какие-либо ошибки.

0
ответ дан 7 December 2019 в 01:21
поделиться

Я думаю, что вам может пропустить здесь, - это переплета Twoway на выставке. Когда вы связываете ваш класс ViewModel, который содержит MyList (связанные элементыSource) и MyLiSelection (BOND для вызова в вашем случае) всегда будет иметь эту информацию, даже если вы пошли на разные вкладки. Поэтому, когда вы вернетесь к этой вкладке, MyLiSelection будет связывать обратно в Comboboc.SelecedItem снова, и вы будете хорошими. Попробуйте это и дайте мне знать.

0
ответ дан 7 December 2019 в 01:21
поделиться

Я думаю, что это может быть решено простым нулевым чеком.

public TestViewModel SelectedTest
{
    get { return _SelectedTest; }
    set
    {
        if(value != null)
            _SelectedTest = value;
        OnPropertyChanged("SelectedTest");
    }
}

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

0
ответ дан 7 December 2019 в 01:21
поделиться

Отредактировано после изменения в ОП. Привет, Хосе, я не могу воспроизвести ошибку, которую вы упоминаете. Таким образом, ваше предположение о разрушении контроля неправильно. Combobox ведет себя, как ожидается, с кодом ниже даже он теперь использует ссылочный тип. Некоторая другая часть вашего кода должна пинать при изменении Tabitems.

<Window x:Class="ComboBoxInTabItemSpike.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="300" Width="300">
    <StackPanel>
        <TabControl>
            <TabItem Header="1">
                <ComboBox ItemsSource="{Binding MyList}"
                          SelectedItem="{Binding MySelect}"/>
            </TabItem>
            <TabItem Header="2"/>
        </TabControl>
        <TextBlock Text="{Binding MySelect}"/>
    </StackPanel>
</Window>

using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Windows;

namespace ComboBoxInTabItemSpike
{
    public partial class Window1 : Window, INotifyPropertyChanged
    {
        public Window1()
        {
            InitializeComponent();
            MyList=new ObservableCollection<TestObject>(
                new[]{new TestObject("1"),new TestObject("2"),new TestObject("3") });
            DataContext = this;
        }

        public ObservableCollection<TestObject> MyList { get; set; }

        private TestObject mySelect;
        public TestObject MySelect
        {
            get { return mySelect; }
            set{ mySelect = value;
            if(PropertyChanged!=null)
                PropertyChanged(this,new PropertyChangedEventArgs("MySelect"));} 
        }

        public TestObject MySelectedItem
        {
            get { return (TestObject)GetValue(MySelectedItemProperty); }
            set { SetValue(MySelectedItemProperty, value); }
        }

        public static readonly DependencyProperty MySelectedItemProperty =
            DependencyProperty.Register("MySelectedItem",
                                typeof(TestObject),
                                typeof(Window1),
                                new UIPropertyMetadata(null));

        public event PropertyChangedEventHandler PropertyChanged;
    }

    public class TestObject
    {
        public string Name { get; set; }

        public TestObject(string name)
        {
            Name = name;
        }

        public override string ToString()
        {
            return Name;
        }
    }
}
0
ответ дан 7 December 2019 в 01:21
поделиться
Другие вопросы по тегам:

Похожие вопросы: