我有2个组合框,一个包含'Items'列表,另一个包含'Subitems'列表。
子项列表取决于当前选择的项目。
我已经完成了大部分工作(通过将Subitems的ItemSource绑定到PossibleSubitems属性),但问题是当我更改Item并且Subitem对新项目不再有效时。在这种情况下,我只想选择第一个有效的子项目,但我得到一个空白的组合框。请注意,我认为类中的属性设置正确,但绑定似乎没有正确反映它。
这里有一些代码可以告诉你我在做什么。在这种情况下,我有: 'Item 1',可以有SubItem A或Subitem B和 '第2项'可以有SubItem B或Subitem C
当我选择了Subitem A时切换到第2项时会出现问题。
XAML
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="134" Width="136">
<StackPanel Height="Auto" Width="Auto">
<ComboBox ItemsSource="{Binding PossibleItems, Mode=OneWay}" Text="{Binding CurrentItem}"/>
<ComboBox ItemsSource="{Binding PossibleSubitems, Mode=OneWay}" Text="{Binding CurrentSubitem}"/>
</StackPanel>
</Window>
代码背后:
using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Windows;
namespace WpfApplication1
{
public partial class MainWindow : Window, INotifyPropertyChanged
{
// List of potential Items, used to populate the options for the Items combo box
public ObservableCollection<string> PossibleItems
{
get
{
ObservableCollection<string> retVal = new ObservableCollection<string>();
retVal.Add("Item 1");
retVal.Add("Item 2");
return retVal;
}
}
// List of potential Items, used to populate the options for the Subitems combo box
public ObservableCollection<string> PossibleSubitems
{
get
{
ObservableCollection<string> retVal = new ObservableCollection<string>();
if (CurrentItem == PossibleItems[0])
{
retVal.Add("Subitem A");
retVal.Add("Subitem B");
}
else
{
retVal.Add("Subitem B");
retVal.Add("Subitem C");
}
return retVal;
}
}
// Track the selected Item
private string _currentItem;
public string CurrentItem
{
get { return _currentItem; }
set
{
_currentItem = value;
// Changing the item changes the possible sub items
NotifyPropertyChanged("PossibleSubitems");
}
}
// Track the selected Subitem
private string _currentSubitem;
public string CurrentSubitem
{
get { return _currentSubitem; }
set
{
if (PossibleSubitems.Contains(value))
{
_currentSubitem = value;
}
else
{
_currentSubitem = PossibleSubitems[0];
// We're not using the valuie specified, so notify that we have in fact changed
NotifyPropertyChanged("CurrentSubitem");
}
}
}
public MainWindow()
{
InitializeComponent();
this.DataContext = this;
CurrentItem = PossibleItems[0];
CurrentSubitem = PossibleSubitems[0];
}
public event PropertyChangedEventHandler PropertyChanged;
internal void NotifyPropertyChanged(String propertyName = "")
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
}
答案 0 :(得分:2)
我重写了我自己的样本 - 保留了代码,以免过多地偏离你的样本。此外,我使用的是.NET 4.5,因此无需在OnPropertyChanged调用中提供属性名称 - 如果在.NET 4.0上,则需要插入它们。这适用于所有情况。
实际上,我建议根据MVVM模式在视图模型中查找此代码。除了DataContext的绑定之外,它与这个实现看起来并没有太大的不同。
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Windows;
namespace WpfApplication1
{
public partial class MainWindow: Window, INotifyPropertyChanged
{
private string _currentItem;
private string _currentSubitem;
private ObservableCollection<string> _possibleItems;
private ObservableCollection<string> _possibleSubitems;
public MainWindow()
{
InitializeComponent();
LoadPossibleItems();
CurrentItem = PossibleItems[0];
UpdatePossibleSubItems();
DataContext = this;
CurrentItem = PossibleItems[0];
CurrentSubitem = PossibleSubitems[0];
PropertyChanged += (s, o) =>
{
if (o.PropertyName != "CurrentItem") return;
UpdatePossibleSubItems();
ValidateCurrentSubItem();
};
}
private void ValidateCurrentSubItem()
{
if (!PossibleSubitems.Contains(CurrentSubitem))
{
CurrentSubitem = PossibleSubitems[0];
}
}
public ObservableCollection<string> PossibleItems
{
get { return _possibleItems; }
private set
{
if (Equals(value, _possibleItems)) return;
_possibleItems = value;
OnPropertyChanged();
}
}
public ObservableCollection<string> PossibleSubitems
{
get { return _possibleSubitems; }
private set
{
if (Equals(value, _possibleSubitems)) return;
_possibleSubitems = value;
OnPropertyChanged();
}
}
public string CurrentItem
{
get { return _currentItem; }
private set
{
if (value == _currentItem) return;
_currentItem = value;
OnPropertyChanged();
}
}
public string CurrentSubitem
{
get { return _currentSubitem; }
set
{
if (value == _currentSubitem) return;
_currentSubitem = value;
OnPropertyChanged();
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void LoadPossibleItems()
{
PossibleItems = new ObservableCollection<string>
{
"Item 1",
"Item 2"
};
}
private void UpdatePossibleSubItems()
{
if (CurrentItem == PossibleItems[0])
{
PossibleSubitems = new ObservableCollection<string>
{
"Subitem A",
"Subitem B"
};
}
else if (CurrentItem == PossibleItems[1])
{
PossibleSubitems = new ObservableCollection<string>
{
"Subitem B",
"Subitem C"
};
}
}
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
答案 1 :(得分:1)
你正在通知错误的财产。在CurrentItem
,您拨打"PossibleSubitems"
。
private string _currentItem;
public string CurrentItem
{
get { return _currentItem; }
set
{
_currentItem = value;
// Changing the item changes the possible sub items
NotifyPropertyChanged("PossibleSubitems");
}
}
修复此问题并重试:)
警告......这是一个蠢事...... 我改变它是为了使它工作(只因为我很好奇),但这绝不是正确的方式,也不是优雅的方式:
// List of potential Items, used to populate the options for the Subitems combo box
public ObservableCollection<string> PossibleSubitems { get; set; }
// Track the selected Item
private string _currentItem;
public string CurrentItem
{
get { return _currentItem; }
set
{
_currentItem = value;
// Changing the item changes the possible sub items
if (value == "Item 1")
PossibleSubitems = new ObservableCollection<string>() {"A","B"} ;
else
PossibleSubitems = new ObservableCollection<string>() { "C", "D" };
RaisePropertyChanged("CurrentItem");
RaisePropertyChanged("PossibleSubitems");
}
}
所以基本上,当前项目发生变化时,它会创建新的子项集合...
丑陋 !!!我知道......你可以重复使用这些系列,并做很多其他事情......但正如我所说,我很好奇是否可以这样做......:)
如果这会打破你的键盘,或者你的猫跑掉了,我就不承担任何责任。