[英]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.