我有2个控件都绑定到相同的依赖属性“Weather”。 在第一个控件中放置当前天气,另一个显示预测。
在我的第一个控件的XAML中,我绑定了一个包含“Humidity”的TextBox,如下所示。
<TextBox Text="{Binding Weather.Humidity}" />
每当湿度发生变化时,我希望其他控制器做一些事情,但是只改变湿度不会改变天气 - 所以另一个控制它没有通知。改变湿度应改变整个预测。
(我实际上并没有写一个天气应用程序,但只是使用上面的例子)
我的问题:这样做的正确方法是什么?我能想到的唯一方法是在TextBox上设置一个触及Weather属性的SourceUpdated事件处理程序。有更优雅的方式吗?
由于
答案 0 :(得分:1)
TextBox绑定上的UpdateSourceTrigger属性的默认值是'LostFocus'您应该做的一件事是将其更改为PropertyChanged,然后Humidity属性将反映您在TextBox中输入时的任何更改。
接下来,您要确保您的Weather Class实现INotifyPropertyChanged,如下所示:
public class Weather : INotifyPropertyChanged
{
private int myHumidity;
public int Humidity
{
get
{
return this.myHumidity;
}
set
{
this.myHumidity = value;
NotifyPropertyChanged("Humidity");
}
}
private void NotifyPropertyChanged(String info)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(info));
}
}
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
#endregion
}
这将确保向用户通知Humidity属性的任何更改。
答案 1 :(得分:1)
我认为你希望其他控件做某事的原因是因为湿度会影响天气/预报的其他属性。在这种情况下,您实现INotifyPropertyChanged,就像在rmoore的答案中一样,并确保在修改湿度时,它显式更改其他属性,触发其通知更新,或者发送更新通知,如下所示:
private int myHumidity;
public int Humidity
{
get
{
return this.myHumidity;
}
set
{
this.myHumidity = value;
NotifyPropertyChanged("Humidity");
NotifyPropertyChanged("MyOtherProperty");
}
}
答案 2 :(得分:0)
一个简单的绑定方案将是这样的:
这可能会有所帮助:
<Window x:Class="BindingSample.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
WindowStartupLocation="CenterScreen"
Title="BindingDemo" Height="300" Width="300">
<Grid>
<StackPanel Margin="20">
<Slider Name="fontSizeSlider" Minimum="0"
Maximum="100" Value="{Binding Path=Weather.Humidity, Mode=TwoWay}"/>
<Label Content="Enter Humidity (between 0 to 100)" />
<TextBox x:Name="_humidity"
Text="{Binding Path=Weather.Humidity,
Mode=TwoWay,
UpdateSourceTrigger=PropertyChanged}"
/>
<TextBlock Text=" "/>
<Label Content="Forecast: " />
<TextBlock
Text="{Binding Path=Weather.Forecast}"
Foreground="Blue"
FontSize="{Binding ElementName=_humidity,Path=Text}" />
</StackPanel>
</Grid>
</Window>
Weather类可以如下:
public class DummyViewModel
{
public Weather Weather { get; set; }
public DummyViewModel()
{
this.Weather = new Weather();
}
public DummyViewModel(int humidity):this()
{
this.Weather.Humidity = humidity;
}
}
public class Weather : INotifyPropertyChanged
{
#region - Fields -
private string _forecast;
private decimal _humidity;
#endregion // Fields
#region - Constructor -
#endregion // Constructor
#region - Properties -
public string Forecast
{
get { return _forecast; }
set
{
if (value == _forecast)
return;
_forecast = value;
this.OnPropertyChanged("Forecast");
}
}
public decimal Humidity
{
get { return _humidity; }
set
{
if (value == _humidity)
return;
_humidity = value;
this.OnPropertyChanged("Humidity");
UpdateForeCast();
}
}
#endregion // Properties
#region - Private Methods -
private void UpdateForeCast()
{
if (this.Humidity < 0 || this.Humidity > 100)
this.Forecast = "Unknown";
else if (this.Humidity >= 70)
this.Forecast = "High";
else if (this.Humidity < 40)
this.Forecast = "Low";
else
this.Forecast = "Average";
}
#endregion
#region INotifyPropertyChanged Members
/// <summary>
/// Raised when a property on this object has a new value.
/// </summary>
public event PropertyChangedEventHandler PropertyChanged;
/// <summary>
/// Raises this object's PropertyChanged event.
/// </summary>
/// <param name="propertyName">The property that has a new value.</param>
protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = this.PropertyChanged;
if (handler != null)
{
var e = new PropertyChangedEventArgs(propertyName);
handler(this, e);
}
}
#endregion // INotifyPropertyChanged Members
}
然后你可以这样:
public Window1()
{
InitializeComponent();
this.DataContext = new DummyViewModel(40);
}
或M-V-VM风格
Window1 view = new Window1();
view.DataContext new DummyViewModel(40);
view.Show();