簡體   English   中英

WPF ComboBox SelectedItem

[英]WPF ComboBox SelectedItem

好的,我一直在與WPF合作,但我需要一些幫助。

我有一個如下的ComboBox

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

每當我離開標簽1然后回到它時,選擇就會被移除。 我認為這樣做的原因是控件在超出范圍然后重新進入時會被銷毀。但是在過程中,SelectedItem變為null,這不是用戶想要的,因為UI是一個事件生命周期。

所以我想知道最佳路線是什么? 我正在使用MVVM構建這個應用程序,所以我可以忽略我的ViewModel中的MyListSelection屬性的set調用,但是我在整個地方都有ComboBox,並且不喜歡修改我的ViewModel,因為我認為它是WPF的一個bug。

我可以子類化WPF ComboBox,但是沒有SelectedItemChanging事件我只能在SelectedItem更改時添加處理程序。

有任何想法嗎?

更新:

好吧,在我的頭撞牆后,我發現為什么我的問題無法復制。 如果列表項類型由於某種原因是一個類,則由WPF將SelectedItem設置為null,但如果它是值類型則不會。

這是我的測試類(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更改為int類型並在選項卡之間來回切換時,SelectedItem保持不變。 但是當它是TestViewModel類型時,當tabitem失焦時,SelectedTest被設置為null。

這是怎么回事?

我有完全相同的問題,直到現在我無法弄清問題是什么。 我在具有相同操作系統,.Net版本和硬件規格的4台不同機器上進行了測試,並且可以在其中兩個機器中重現這個問題,而在其他機器中工作得很好。 我能找到適合我的解決方法是在ItemsSource之前定義SelectedItem綁定。 奇怪的是,如果我遵循這種模式,一切都按預期工作。 也就是說,你只需要做以下事情:

<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>

OP改變后編輯。 嗨,何塞,我無法再現你提到的錯誤。 因此,關於控制被破壞的假設是錯誤的。 即使現在使用引用類型,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;
        }
    }
}

我建議檢查綁定。 如果您的應用中的任何其他內容正在更改所選項目或項目來源,那么您的綁定將會中斷。 您還可以在輸出窗口中查看Visual Studio以查看是否存在任何錯誤。

我想你在這里可能缺少的是SelectedItem上的TwoWay綁定。 當你綁定包含MyList(綁定的ItemsSource)的ViewModel類和MyListSelection(你的Case中的Bond到SelectedItem)時,即使你去了不同的標簽,它們也總會有這些信息。 因此,當您返回此Tab時,MyListSelection將再次綁定回ComboBoc.SelectedItem,您將會很好。 試試這個讓我知道。

我認為這可以通過簡單的空檢查來解決。

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

這是因為ComboBox在回收時有重置SelectedIndex的傾向。 這個簡單的空檢查將強制它重新綁定到最后一個有效項。

我的列表中的引用類型遇到了完全相同的問題。 解決方案是在TestViewModel中重寫Equals(),以便WPF能夠在對象之間執行值相等性檢查(而不是引用檢查),以確定哪個是SelectedItem。 我碰巧有一個ID字段,它實際上是TestViewModel的識別功能。

組合框的這種行為應該由編譯器以比它更好的方式實現...... IE編譯器應檢查並查看ItemsSource的類型和SelectedItem綁定的屬性的類型引用值是否將永遠返回一個可比較的值

它應該警告您可以考慮重寫Equals()和GetHashCode()方法......

今天浪費了很多時間!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM