WPF DependencyProperty不在WPF UserControl(ElementHost)中更新

时间:2012-06-14 07:10:49

标签: c# .net wpf winforms office-interop

我构建了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;
}       

此致 托马斯

2 个答案:

答案 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);