2009-06-05 36 views
13

我有一個對象不能繼承DependencyObject,或者使用NotifyPropertyChanged,我將它綁定到了很多控件上,所以當屬性發生變化時,我不想去每個控件並改變它是在代碼值,所以我想必須有一個方法來告訴XAML爲「重新綁定」所有,它的綁定到的代碼的一個或兩行,而不是去:那麼在WPF Force rebind

label1.Content = myObject.DontNotifyThis; 
label2.Content = myObject.DontNotifyThisEither; 
label3.Content = myObject.DontEvenThinkOfNotifyingThis; 
label4.Content = myObject.NotSoFastPal; 

,等等...

這是一個過於簡單的例子:

XAML:

<Window x:Class="StackOverflowTests.Window1" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    Title="Window1" x:Name="window1" Height="300" Width="300" Loaded="window1_Loaded"> 
    <Grid x:Name="gridMain"> 
     <Grid.RowDefinitions> 
      <RowDefinition Height="Auto" /> 
      <RowDefinition Height="Auto" /> 
      <RowDefinition Height="Auto" /> 
     </Grid.RowDefinitions> 
     <Label Grid.Row="0" Content="{Binding Status}" ContentStringFormat="Today's weather: {0}" /> 
     <Label Grid.Row="2" Content="{Binding Temperature}" ContentStringFormat="Today's temperature: {0}" /> 
     <Label Grid.Row="1" Content="{Binding Humidity}" ContentStringFormat="Today's humidity: {0}" /> 
    </Grid> 
</Window> 

C#:

using System.Windows; 

namespace StackOverflowTests 
{ 
    /// <summary> 
    /// Interaction logic for Window1.xaml 
    /// </summary> 
    public partial class Window1 : Window 
    { 
     Weather weather = new Weather("Cloudy", "60F", "25%"); 

     public Window1() 
     { 
      InitializeComponent(); 
      this.DataContext = weather; 
     } 

     private void window1_Loaded(object sender, RoutedEventArgs e) 
     { 
      weather.Status = "Sunny"; 
      weather.Temperature = "80F"; 
      weather.Humidity = "3%"; 
     }  
    } 

    class Weather 
    { 
     public string Status { get; set; } 
     public string Temperature { get; set; } 
     public string Humidity { get; set; } 

     public Weather(string status, string temperature, string humidity) 
     { 
      this.Status = status; 
      this.Temperature = temperature; 
      this.Humidity = humidity; 
     } 
    } 
} 

我找到了一種方法來做到這一點,但它不是優雅可言的,可惜的是,我不能只是設置的DataContext天氣的一個新實例,它需要是相同的(這就是爲什麼我將它設置爲null,所以它的變化):

private void window1_Loaded(object sender, RoutedEventArgs e) 
{ 
    weather.Status = "Sunny"; 
    weather.Temperature = "80F"; 
    weather.Humidity = "3%"; 

    // bad way to do it 
    Weather w = (Weather)this.DataContext; 
    this.DataContext = null; 
    this.DataContext = w; 
} 

提前感謝!

+0

好奇:爲什麼你不能實施INPC? – 2009-06-05 19:58:22

+0

我們在應用程序上使用撤銷/重做,INotifyPropertyChanging序列化對象的先前狀態,INotifyPropertyChanged啓用將對象保存到新的XmlSerialized文件中。但是,我需要更改的這些特定屬性不會更改對象的保存狀態(不會更改字體,顏色,背景,邊框)或用戶想要保存的任何內容。如果我使用這些屬性NotifyPropertyChanging/Changed,系統會認爲該對象已更改,但對用戶而言,則不是。 這就是爲什麼我不能使用它。 – Carlo 2009-06-05 20:08:12

回答

20

如果您有權訪問要更新綁定的元素,則可以顯式更新綁定。您可以檢索元素上的綁定表達式,然後使用UpdateTarget()刷新UI,或使用UpdateSource刷新支持屬性(如果要綁定到像TextBox一樣可編輯的內容)。

這裏有一個簡單的例子,演示了:

<StackPanel> 
    <TextBlock x:Name="uiTextBlock" Text="{Binding MyString}" /> 
    <Button Click="Button_Click" 
      Content="Rebind" /> 
</StackPanel> 

public partial class Window1 : Window 
{ 
    public string MyString { get; set; } 

    public Window1() 
    { 
     MyString = "New Value"; 

     InitializeComponent(); 
     this.DataContext = this; 
    } 
    int count = 0; 
    private void Button_Click(object sender, RoutedEventArgs e) 
    { 
     MyString = "Rebound " + ++count + " times"; 

     var bindingExpression = uiTextBlock.GetBindingExpression(TextBlock.TextProperty); 
     bindingExpression.UpdateTarget(); 
    } 
} 

(。我會建議使用INotifyPropertyChanged的,雖然如果在所有可能的方式,你可以從代碼中提取背後的邏輯)