2009-01-26 41 views
6

起初我想說下面的示例是過分簡化的。 假設你已經綁定了WPF控件。INotifyPropertyChanged問題

<Window Title="Window1" Height="300" Width="300"> 
<Grid> 
    <StackPanel> 
     <TextBox Text="{Binding Name}" Margin="10"/> 
     <Button HorizontalAlignment="Center" 
     Content="Click Me" Margin="5" 
     Padding="2" Click="OnButtonClick" /> 
    </StackPanel> 
</Grid> 
</Window> 

窗口被綁定到其實現INotifyPropertyChanged並且具有名稱設定器在形式

public string Name 
    { 
     get { return _name; } 
     set 
     { 
      _name = "Some Name"; 
      OnPropertyChanged("Name"); 
     } 
    } 

即Person類每當用戶嘗試從UI更改時,_name都會分配「某個名稱」。 但這個示例不起作用。我將TextBox中的名稱更改爲某個值按Tab鍵強制焦點移動到Button,並且TextBox中的值保持不變,但PropertyChanged事件已觸發。

請你解釋一下爲什麼會發生?據我所知PropertyChanged事件迫使用戶界面重新讀取屬性的值並顯示它們,但在我的示例中,數據綁定文本框中的值未更新。


再次。我明白,這是財產執行不力,但我想重申,這是過於簡單化。 這只是一個例子。 但無論如何,PropertyChanged表示屬性發生了變化,應該更新,但事實並非如此。

+0

犯錯,我可能是錯的,但它不應該是`{綁定路徑=名稱}`? – 2009-01-26 18:27:26

+1

不是。對於屬性綁定,可以省略Path作爲快捷方式。 – 2009-01-26 18:28:57

+1

這是因爲綁定具有將路徑作爲參數的構造函數。 – 2009-01-26 18:31:08

回答

8

PropertyChanged事件被TextBox忽略,因爲它是事件的發起者。

一些澄清:

文本框(或文本框的結合)知道它是引發劑,因爲它在接收同一呼叫PropertyChanged事件。通過執行異步調用,文本框(或綁定)無法知道它是發起者,因此它會像處理其他人更新過的一樣處理事件

如果您向用戶界面添加第二個文本框,您會看到第2個TextBox在編輯1st時會發生變化,反之亦然。

0

原因是因爲你已經對setter中的'Some Name'進行了硬編碼。當你改變textBox值時,setter實際上被調用,並且再次將「Some Name」設置爲propertyValue,所以它似乎不會在UI中被改變。 把_name = value和東西只會如你所料,

0

如果我沒有錯,TextBox的Text屬性的默認綁定行爲是TwoWay,所以這應該工作。您可以強制它是雙向像這樣的XAML:

<Window Title="Window1" Height="300" Width="300"> 
    <Grid> 
    <StackPanel> 
     <TextBox Text="{Binding Name, Mode=TwoWay}" Margin="10"/> 
     <Button HorizontalAlignment="Center" 
     Content="Click Me" Margin="5" 
     Padding="2" Click="OnButtonClick" /> 
    </StackPanel> 
    </Grid> 
</Window> 

注意Mode=TwoWay在綁定聲明。

如果這不起作用,那麼我懷疑在觸發事件的代碼中拋出異常,或者分配屬性,並且應該查找該異常。


似乎有可能您正在調用不是UI線程的線程上的值。如果是這種情況,那麼您必須編組調用來觸發UI線程上的屬性更改事件,或者更改UI線程上的值。

當對象綁定到UI元素時,必須在UI線程上對可能影響UI的對象進行更改。

0
public string MyField 
{ 
    get { return _myField; } 
    set { 
     if (_myField == value) 
      return; 

     _myField = value; 

     OnPropertyChanged("MyField"); 
    } 
} 

這是該屬性的正確實施。

當您更改屬性時,請確保該對象的EXACT相同實例綁定到控件。否則,將通知更改,但控制永遠不會得到它,因爲控件沒有正確綁定。

0

形式

 set 
     { 
      _name = "Some Name"; 
      Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.DataBind, 
       (SendOrPostCallback)delegate { OnPropertyChanged("Name"); }, 
       null); 
     } 

更換二傳手解決問題,但它仍然是開放的。爲什麼我應該做異步調用,而不是同步信號,我的屬性已被更改。

2

由於Bubblewrap已經指出,這是由設計 - 文本框假設,如果它將綁定屬性設置爲某個值,setter將不會更改該值。 According to Microsoft,它們不會改變這種行爲,因爲這會破壞現有的代碼。

如果你想想要改變這個值(是的,這樣做有很好的理由),你必須使用一個解決方法,例如通過添加一個虛擬轉換器。有a blog entry(不是我寫的)詳細描述這種技術。通過Heinzi建議

4

僞轉換器解決方法(描述here)當綁定的UpdateSourceTrigger的PropertyChanged不起作用。但如果這是我們需要的呢?

似乎使得結合 - 異步的伎倆,例如:

SelectedIndex="{Binding SelectedIndex, IsAsync=True}"