【问题标题】:The proper way to do this - binding to properties执行此操作的正确方法 - 绑定到属性
【发布时间】:2009-06-04 14:32:48
【问题描述】:

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

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

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

每当湿度发生变化时,我希望其他控件执行某些操作,但是仅更改湿度不会改变天气 - 所以它不会通知其他控件。改变湿度应该会改变整个预测。

(我实际上不是在写天气应用,只是用上面的例子)

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

谢谢

【问题讨论】:

  • 您能否提供更多信息,说明您如何显示预报以及这与您的湿度显示有何关系?这一切都是在一个控件中完成的吗?此外,湿度与“天气”对象中的另一个属性之间是否存在内部关系?你看过 INotifyPropertyChanged 接口吗?

标签: c# .net wpf xaml


【解决方案1】:

我认为您希望其他控件执行某些操作的原因是因为湿度会影响天气/预测的其他一些属性。在这种情况下,您实现 INotifyPropertyChanged,就像 rmoore 的回答一样,并确保在修改湿度时,它要么显式更改其他属性,触发其通知更新,要么发送更新通知,如下所示:

private int myHumidity;
            public int Humidity
            {
                    get
                    {
                            return this.myHumidity;
                    }
                    set
                    {
                            this.myHumidity = value;
                            NotifyPropertyChanged("Humidity");
                            NotifyPropertyChanged("MyOtherProperty");
                    }
            }

【讨论】:

  • 是的,这最符合我的场景 - 谢谢我会这样实现它
【解决方案2】:

TextBox 绑定上 UpdateSourceTrigger 属性的默认值是“LostFocus”,您应该将其更改为 PropertyChanged,然后 Humidity 属性将反映您在 TextBox 中输入的任何更改。

接下来,您要确保您的 Weather 类实现 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
    }

这将确保 UI 收到有关 Humidity 属性的任何更改的通知。

【讨论】:

    【解决方案3】:

    一个简单的绑定场景是这样的:

    这可能会有所帮助:

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

    【讨论】:

      猜你喜欢
      • 2013-03-25
      • 2014-09-26
      • 2021-08-23
      • 1970-01-01
      • 2013-02-24
      • 2019-04-20
      • 1970-01-01
      • 2019-02-24
      • 1970-01-01
      相关资源
      最近更新 更多