2012-06-14 113 views
1

我構建了一個Office 2010 Word添加,添加了一個Windows窗體元素,並在那裏包含我的WPF的ElementHost對象。WPF DependencyProperty不在WPF中更新用戶控件(ElementHost)

這就是問題: 我得到了問題,在Xaml代碼中定義並在ViewModel實現中設置的常見屬性(DP)未更新,即使我找不到任何錯誤的代碼同時調試。這隻適用於我得到的屬性,此外我得到了一些 ObservableCollection <> List的更新沒有任何問題。有任何想法?我紅,我可以通過自己的代碼中使用這樣的定義屬性:

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

但是,這並不工作過(我只是說此行到例如代碼隱藏XAML文件的文件 - 在這人離開一切皆有)

我的代碼看起來是這樣的:

的形式構造元素(它實際上是私人,因爲我實現了它作爲單件):

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

我的視圖模型屬性定義,並用這樣的方式:

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 <>列表更新,但不是必然的屬性,如

<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

使用調度對象,已用於項目的插入到UI綁定列表,是成功完成這一任務的關鍵在於:

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

1)檢查你的輸出窗口綁定錯誤。 (雖然他們看起來對我來說)

2)我的直接想法是PropertyChanged事件不會被你的ViewModel正確提出。你能否展示SetField()的實現?我認爲這是去除INotifyPropertyChanged固有的魔法字符串的一些包裝?

+0

關於2)你是對的,看到上面的實現。其實我和你一樣,綁定對我也很好。這就是爲什麼我不能猜測哪裏可能會出現錯誤...... :( – inva

+0

你能調試,以確保它正在適當提出正確的名稱? – GazTheDestroyer

+0

我已經這樣做了,我調試,直到OnPropertyChanged的最終調用(字符串)具有確切的名稱,這將在這種情況下「NumberOfPeople」 - 但不幸的事件不處理某種方式=/ – inva