我有一个DataContext对象:
//Simple DataContext object with an observable collection and a property representing the currently selected project which uses the INotifyPropertyChanged interface
public class ProjectManager: ObservableObject
{
public ObservableCollection<Project> Projects {get;set;}
public ProjectManager()
{
//Assignment occurs in constructor and never changes, so I don't think "Projects" property needs to implement INotifyPropertyChanged. It has a value by the time anything else could possibly reference it and it's always the same collection which will have items added and removed from it
Projects = new ObservableCollection<Project>();
}
private Project loadedProject = null;
public Project CurrentProject
{
get {return loadedProject;}
set
{
LoadProject( value ); //load the project before updating internal variable
SetProperty( ref loadedProject, value ); //SetProperty uses C# 5.0 [CallerMemberName] attribute on optional parameter to obtain "CurrentProject" property name since it's the caller; this is a popular implementation of ObservableObject
}
}
}
我有一个表示可观察集合中项目的类:
public class Project: ObservableObject
{
private string _name;
public string Name
{
get {return _name;}
set {SetProperty( ref _name, value );} //ObservableObject implements INotifyProperyChanged
}
}
ObservableObject在这里实现:
public class ObservableObject: INotifyPropertyChanged
{
//C# 5.0 feature: "CallerMemberName" must be affixed to *optional* parameter and is automatically filled in with the member name of the method that calls SetProperty when the parameter is omitted
protected bool SetProperty<T>( ref T prop, T value, [CallerMemberName] string propertyName = null )
{
if (EqualityComparer<T>.Default.Equals(prop,value)) return false;
prop = value;
OnPropertyChanged( propertyName );
return true;
}
protected void OnPropertyChanged( string propertyName )
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
handler(this, new PropertyChangedEventArgs(propertyName));
}
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
#endregion
}
ProjectManager实例被分配给我在XAML中的Window的DataContext属性,如下所示:
<Window.DataContext>
<p:ProjectManager />
</Window.DataContext>
在运行时,调试器的本地窗口显示我的窗口的DataContext属性包含ProjectManager类的实例,因此我知道DataContext正确设置并且应该可用于儿童控制。
在Window中,我的ComboBox具有以下属性集:
ItemsSource="{Binding Projects, Mode=OneWay}" DisplayMemberPath="Name" SelectedValuePath="Name" SelectedValue="{Binding CurrentProject, UpdateSourceTrigger=PropertyChanged}"
最初,Projects observable集合为空。预期的行为是,当用户单击按钮并调用Projects.Add(新项目(&#34; ProjectName&#34;))时,组合框应检测到可观察集合已更改并应将新项目添加到自身至少。但是,组合框中根本没有任何东西出现。
答案 0 :(得分:1)
我们能看到你的ObservableObject代码吗?我看不出你的绑定有什么问题。如果我实现你所描述的如下所示,一切都按预期工作,这让我认为这是你的INotifyPropertyChanged实现。
public class ObservableObject : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected void RaisePropertyChangedEvent(string propertyName)
{
var Handler = PropertyChanged;
if (Handler != null)
Handler(this, new PropertyChangedEventArgs(propertyName));
}
}
Projects / DataContext:
public class ProjectManager : ObservableObject
{
public ObservableCollection<Project> Projects { get; set; }
public ProjectManager()
{
Projects = new ObservableCollection<Project>();
}
private Project loadedProject = null;
public Project CurrentProject
{
get { return loadedProject; }
set
{
//LoadProject(value); //load the project before updating internal variable
//SetProperty(ref loadedProject, value); //SetProperty uses C# 5.0 [CallerMemberName] attribute on optional parameter to obtain "CurrentProject" property name since it's the caller; this is a popular implementation of ObservableObject
loadedProject = value;
RaisePropertyChangedEvent("CurrentProject");
}
}
}
public class Project : ObservableObject
{
private string _name;
public string Name
{
get { return _name; }
//set { SetProperty(ref _name, value); } //ObservableObject implements INotifyProperyChanged
set { _name = value; RaisePropertyChangedEvent("Name"); }
}
}
按钮点击:
private void Button_Click(object sender, RoutedEventArgs e)
{
ProjectManager PM = DataContext as ProjectManager;
PM.Projects.Add(new Project() { Name = "New Project"});
}
XAML:
<Window.DataContext>
<pr:ProjectManager/>
</Window.DataContext>
<Grid>
<StackPanel Orientation="Horizontal" Height="32">
<Button Height="32" Click="Button_Click">Bind</Button>
<ComboBox Height="32" Width="400" ItemsSource="{Binding Projects}" DisplayMemberPath="Name"
SelectedValuePath="Name" SelectedValue="{Binding CurrentProject}"></ComboBox>
</StackPanel>
</Grid>
按下Bind后的结果: