我构建了Office 2010 Word Add In,在其中添加了一个Windows窗体元素,并在包含我的WPF的ElementHost对象中。
这就是问题所在: 我遇到了问题,即使在调试时找不到任何错误的代码,Xaml代码中定义的公共属性(DP)在ViewModel实现中设置(参见下面的代码)也不会更新。这仅适用于我得到的属性,而且我得到了一些 的ObservableCollection<>列表的更新没有任何问题。有人有个主意吗?我认为我可以在代码中使用以下内容定义属性:
public static readonly DependencyProperty DataSourceProperty = DependencyProperty.Register("DataSource",typeof(string),typeof(usercontrol1));
但这也不起作用(我只是将这一行添加到Xaml文件的代码隐藏文件中 - 并留下其他任何内容)
我的代码看起来像这样:
Forms元素的构造函数(它实际上是私有的,因为我将其实现为Singleton):
private Sidebar()
{
InitializeComponent();
this.DoubleBuffered = true;
_wpfHost = new ElementHost();
_wpfHost.Dock = DockStyle.Fill;
_wpfUserControl = new WPFUI();
_wpfHost.Child = _wpfUserControl;
this.Controls.Add(_wpfHost);
}
此外,我创建了一个底层的ViewModel并将其设置为WPFUI的DataContext属性(这也是一个Singleton实现,因为我想在另一个实现中访问来自多个地方的相同实例,但这不会进入游戏此时):
public WPFUI()
{
InitializeComponent();
this.DataContext = myViewModel.GetInstance();
}
我的ViewModel属性以这种方式定义和使用:
public ObservableCollection<myListViewItem> PeopleEntityResultObjects { get; private set; }
private string _NumberOfPeople;
public string NumberOfPeople
{
get { return _NumberOfPeople; }
set { SetField(ref _NumberOfPeople, value, () => NumberOfPeople); }
}
最后Xaml看起来像这样:
<TabControl>
<TabItem>
<TabItem.Header>
<StackPanel Orientation="Horizontal">
<TextBlock Text=" People "/>
<TextBlock Text="{Binding Path=NumberOfPeople}"/>
</StackPanel>
</TabItem.Header>
<ScrollViewer x:Name="PeopleListScrollViewer">
<ListView Name="PeopleListView" ItemsSource="{Binding Path=PeopleEntityResultObjects, Mode=OneWay}" IsSynchronizedWithCurrentItem="True">
.
.
.
</ListView>
</ScrollViewer>
</TabItem>
</TabControl>
为什么我的ObservableCollection&lt;&gt;列出更新但不包括绑定属性,如
<TextBlock Text="{Binding Path=NumberOfPeople}"/>
?任何人都可以猜测,或者我错过了一些基本的属性定义? (在wpf应用程序中,它正在以这种方式工作)。
修改的
SetField()实现:
protected virtual void OnPropertyChanged<T>(Expression<Func<T>> selectorExpression)
{
if (selectorExpression == null)
throw new ArgumentNullException("selectorExpression");
MemberExpression body = selectorExpression.Body as MemberExpression;
if (body == null)
throw new ArgumentException("The body must be a member expression");
OnPropertyChanged(body.Member.Name);
}
protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
handler(this, new PropertyChangedEventArgs(propertyName));
}
protected bool SetField<T>(ref T field, T value, Expression<Func<T>> selectorExpression)
{
if (EqualityComparer<T>.Default.Equals(field, value)) return false;
field = value;
OnPropertyChanged(selectorExpression);
return true;
}
此致 托马斯
答案 0 :(得分:1)
1)检查输出窗口是否存在绑定错误。 (虽然他们看起来对我很好)
2)我的直接想法是ViewModel没有正确地引发PropertyChanged
个事件。你能否展示一下SetField()
的实施情况?我假设它是一些用于删除INotifyPropertyChanged
中固有的神奇字符串的包装器?
答案 1 :(得分:0)
使用已经用于将项目插入UI绑定列表的调度程序对象是成功完成此任务的关键:
if (DispatcherObject.Thread != Thread.CurrentThread)
DispatcherObject.Invoke(new Action(() => SetField(ref _numberOfPeople, value, () => NumberOfPeople)));
else
SetField(ref _numberOfPeople, value, () => NumberOfPeople);