简体   繁体   English

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

[英]WPF DependencyProperty not updating in WPF UserControl (ElementHost)

I build up a Office 2010 Word Add In, added a Windows Forms Element to it and there in an ElementHost object containing my WPF. 我构建了一个Office 2010 Word加载项,向其中添加了Windows Forms元素,并在其中包含我的WPF的ElementHost对象中。

That's the problem: I got the problem, that common properties (DP's) defined in the Xaml code and set in the ViewModel implementation (see code below) are not updated, even if I can't find any wrong code while debugging. 这就是问题所在:我遇到的问题是,即使我在调试时找不到任何错误的代码,也不会更新Xaml代码中定义的通用属性(DP)和ViewModel实现中设置的公共属性(参见下面的代码)。 This applies only to the properties I got, furthermore i got some ObservableCollection<> List's which are updated without any problems. 这仅适用于我得到的属性,此外,我得到了一些ObservableCollection <> List,这些属性已更新,没有任何问题。 Got anybody an idea? 有任何想法吗? I red that I may define the properties by myself within the Code using something like this: 我同意可以在代码中自己定义属性,如下所示:

public static readonly DependencyProperty DataSourceProperty = DependencyProperty.Register("DataSource",typeof(string),typeof(usercontrol1));

But this does not work too (I just added this line for example into the code-behind file of the Xaml file - and left anything else at it is) 但这还是行不通的(例如,我只是将此行添加到Xaml文件的代码隐藏文件中,并保留了其他任何内容)

My code looks this way: 我的代码看起来像这样:

Constructor of the Forms Element (it's actually private because I implemented it as Singleton): 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);
}

Furthermore I created an underlying ViewModel and set this as DataContext Property of the WPFUI like this (it's also a Singleton implementation because I wanted to access in a further implementation the same instance from several places, but this does not come into the game at this time): 此外,我创建了一个底层ViewModel,并将其设置为WPFUI的DataContext属性,如下所示(它也是一个Singleton实现,因为我想在其他实现中从多个位置访问相同的实例,但是目前尚不存在。 ):

public WPFUI()
{
    InitializeComponent();

    this.DataContext = myViewModel.GetInstance();
}

My ViewModel properties are defined and used this way: 我的ViewModel属性是通过以下方式定义和使用的:

public ObservableCollection<myListViewItem> PeopleEntityResultObjects { get; private set; }

private string _NumberOfPeople;
public string NumberOfPeople
{
    get { return _NumberOfPeople; }
    set { SetField(ref _NumberOfPeople, value, () => NumberOfPeople); }
}

And finally the Xaml looks like this: 最后,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>

Why is my ObservableCollection<> List updating but not the bound properties like 为什么我的ObservableCollection <>列表会更新,但绑定属性不会更新,例如

<TextBlock Text="{Binding Path=NumberOfPeople}"/>

? Can anybody guess, or i'm missing some basic property definition? 任何人都可以猜测,或者我缺少一些基本的属性定义吗? (in a wpf application it is working that way). (在wpf应用程序中,它是按照这种方式工作的)。

EDIT 编辑

SetField() implementation: 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;
}       

Regards, Thomas 问候,托马斯

1) Check your output window for binding errors. 1)检查您的输出窗口是否存在绑定错误。 (Although they look ok to me) (尽管它们对我来说还不错)

2) My immediate thought would be that PropertyChanged events are not being raised properly by your ViewModel. 2)我立即想到的是,您的ViewModel没有正确引发PropertyChanged事件。 Can you show the implementation of SetField() ? 您可以显示SetField()的实现吗? I assume it's some wrapper for removing the magic strings inherent in INotifyPropertyChanged ? 我认为这是一些包装程序,用于删除INotifyPropertyChanged固有的魔术字符串?

using the dispatcher object, already used to insert item's into the UI bound list, is the key to accomplish this task successfully: 使用已经用于将项目的对象插入到UI绑定列表中的调度程序对象,是成功完成此任务的关键:

if (DispatcherObject.Thread != Thread.CurrentThread)
    DispatcherObject.Invoke(new Action(() => SetField(ref _numberOfPeople, value, () => NumberOfPeople)));
else
    SetField(ref _numberOfPeople, value, () => NumberOfPeople);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM