正确的方法 - 绑定到属性

时间:2009-06-04 14:32:48

标签: c# .net wpf xaml

我有2个控件都绑定到相同的依赖属性“Weather”。 在第一个控件中放置当前天气,另一个显示预测。

在我的第一个控件的XAML中,我绑定了一个包含“Humidity”的TextBox,如下所示。

<TextBox Text="{Binding Weather.Humidity}" />

每当湿度发生变化时,我希望其他控制器做一些事情,但是只改变湿度不会改变天气 - 所以另一个控制它没有通知。改变湿度应改变整个预测。

(我实际上并没有写一个天气应用程序,但只是使用上面的例子)

我的问题:这样做的正确方法是什么?我能想到的唯一方法是在TextBox上设置一个触及Weather属性的SourceUpdated事件处理程序。有更优雅的方式吗?

由于

3 个答案:

答案 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)

一个简单的绑定方案将是这样的:

WPF Simple DataBinding

这可能会有所帮助:

<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();