2016-11-29 34 views
0

因此,我有這個非常類似的代碼,當我在使用註釋行代碼時單擊按鈕時,GUI中的值是通過綁定更新一切都很好。如果我使用其他兩行(未知),即使我正在通知變化,也不會發生任何事情。當通知屬性發生變化而未指定新的實例屬性時,Wpf綁定不起作用

public partial class MainWindow : Window, INotifyPropertyChanged 
{ 
    private Spot _position = new Spot(0, 0); 
    public Spot Position 
    { 
     get { return _position; } 
     set { _position = value; OnPropertyChanged("Position"); } 
    } 

    public MainWindow() 
    { 
     InitializeComponent(); 
     win.DataContext = this; 
    } 

    public event PropertyChangedEventHandler PropertyChanged; 

    public void OnPropertyChanged(string name) 
    { 
     PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name)); 
    } 

    private void Button_Click(object sender, RoutedEventArgs e) 
    { 
     //Position = new Spot(5,5); 
     Position.UpdateX(5); 
     OnPropertyChanged("Position"); 
    } 
} 

public class Spot 
{ 
    public Spot(int x, int y) 
    { 
     X = x; 
     Y = y; 
    } 

    public void UpdateX(int x) 
    { 
     X += x; 
    } 
    public void UpdateY(int y) 
    { 
     Y += y; 
    } 

    public override string ToString() 
    { 
     return string.Format("{0}; {1}", X, Y); 
    } 

    public int X { get; set; } = 0; 
    public int Y { get; set; } = 0; 
} 

XAML

<StackPanel x:Name="win" Orientation="Vertical" Margin="100"> 
    <Label Content="{Binding Position, UpdateSourceTrigger=PropertyChanged}" Width="100" Height="25"></Label> 
    <Button Width="100" Height="25" Click="Button_Click">Click</Button> 
</StackPanel> 

先感謝您的任何意見。

+3

當您運行Position.UpdateX(5)時,您正在更新X而不是位置。因此它不起作用。在X上實現PropertyChanged,它會工作。並且不需要此行OnPropertyChanged(「Position」);. – adminSoftDK

+0

這兩個未註釋的行對我有用。 –

+0

@adminSoftDK我知道它可以像這樣修復,爲了對付它,我添加了額外的通知。另外,我不想用UI代碼搞亂Spot類。 –

回答

0

這是交易。

首先,擺脫UpdateSourceTrigger=PropertyChanged:該標誌管理何時Mode=TwoWayBinding更新其源屬性。 Label.Content默認綁定OneWay,因爲它不是可編輯的控件。它無法更新其來源。所以不要說,這是一個沒有任何操作。

二:

<Label Content="{Binding Position}" ... /> 

這將完成是Position通話ToString()。但如果Position的值沒有變化,它將不會再次調用ToString()。在相關意義上,它沒有:它仍然是Spot的同一實例,它是最後一次調用ToString()。這可能是一個「優化」。

這將工作:

<Label> 
    <TextBlock> 
     <TextBlock.Text> 
      <MultiBinding StringFormat="{}{0}: {1}"> 
       <Binding Path="Position.X" /> 
       <Binding Path="Position.Y" /> 
      </MultiBinding> 
     </TextBlock.Text> 
    </TextBlock> 
</Label> 

這將工作太:

<Label> 
    <TextBlock> 
     <TextBlock Text="{Binding Position.X, StringFormat='{}{0}: '}" /> 
     <TextBlock Text="{Binding Position.Y}" /> 
    </TextBlock> 
</Label> 

我把TextBlock S IN Label因爲你使用了LabelLabel往往有預設保證金/填充/無論什麼風格與佈局看起來都很相關。

將無法​​正常工作,因爲Label.ContentObject,不String,所以StringFormat將被忽略。相反,你會在VS 輸出窗格約MultiBinding需要一個轉換器得到一個例外:

<Label 
    > 
    <Label.Content> 
     <MultiBinding StringFormat="{}{0}: {1}"> 
      <Binding Path="Position.X" /> 
      <Binding Path="Position.Y" /> 
     </MultiBinding> 
    </Label.Content> 
</Label> 

普通的方式做到這一點是有Spot實現INotifyPropertyChanged。如果Spot的總體使用情況不適合這樣做,那麼您會陷入或多或少的醜陋之中。我自己,我給Position的主人一個UpdatePosition(int deltaX, int deltaY)方法,創建一個新的實例Spot並將其分配給Position。如果視圖模型(或僞裝成視圖模型的窗口)的屬性未實現INotifyPropertyChanged,則將屬性值視爲不可變。

+0

非常感謝:) –