WPF 强制重新绑定
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/957522/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
WPF Force rebind
提问by Carlo
I have an object that can't inherit DependencyObject OR use NotifyPropertyChanged, and I've binded it to quite a few controls, so when the properties change, I don't want to go to each control and change it's value on the code, so I'm thinking there must be a way to tell the XAML to "Rebind" all that it's bound to with one or two lines of code, instead of going:
我有一个不能继承 DependencyObject 或使用 NotifyPropertyChanged 的对象,并且我已经将它绑定到了很多控件,所以当属性发生变化时,我不想去每个控件并更改它在代码上的值,所以我认为必须有一种方法可以告诉 XAML 用一两行代码“重新绑定”它所绑定的所有内容,而不是去:
label1.Content = myObject.DontNotifyThis;
label2.Content = myObject.DontNotifyThisEither;
label3.Content = myObject.DontEvenThinkOfNotifyingThis;
label4.Content = myObject.NotSoFastPal;
So on, so forth...
等等,等等……
This is an oversimplified example:
这是一个过于简单的例子:
XAML:
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#:
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;
}
}
}
I found a way to do it, but it's not elegant at all, and unfortunatelly, I can't just set the DataContext to a new instance of weather, it needs to be the SAME reference (that's why I set it to null so it changes):
我找到了一种方法来做到这一点,但它根本不优雅,不幸的是,我不能将 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;
}
Thanks in advance!
提前致谢!
回答by rmoore
If you have access to the element that you want to update the binding on then you can explicitly update the binding. You can retrieve the Binding Expression on the element and then use UpdateTarget() to refresh the UI, or UpdateSource to refresh the backing property (if you want to bind to something editable like a TextBox).
如果您有权访问要更新绑定的元素,则可以显式更新绑定。您可以检索元素上的绑定表达式,然后使用 UpdateTarget() 刷新 UI,或使用 UpdateSource 刷新支持属性(如果您想绑定到诸如 TextBox 之类的可编辑内容)。
Here's a simple example that demonstrates it:
这是一个演示它的简单示例:
<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();
}
}
(I would recommend using INotifyPropertyChanged though if at all possible. That way you can extract the logic from the code behind.)
(如果可能的话,我建议使用 INotifyPropertyChanged。这样你就可以从后面的代码中提取逻辑。)