Правильный способ сделать это - привязка к свойствам - PullRequest
0 голосов
/ 04 июня 2009

У меня есть 2 элемента управления, которые оба связаны с одним и тем же свойством зависимости "Погода". В первом элементе управления вы указываете текущую погоду, а во втором - прогноз.

В моем XAML первого элемента управления я связываю TextBox с «влажностью» следующим образом.

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

Всякий раз, когда изменяется влажность, я хочу, чтобы другой элемент управления что-то сделал, однако изменение только влажности не меняет погоду - поэтому другой элемент управления не уведомляется. Изменение влажности должно изменить весь прогноз.

(я не пишу приложение о погоде, а просто использую приведенное выше в качестве примера)

Мой вопрос: как правильно это сделать? Единственный способ, о котором я могу думать, - это установить обработчик события SourceUpdated в TextBox, который касается свойства Weather. Есть ли более элегантный способ сделать это?

Спасибо

Ответы [ 3 ]

1 голос
/ 04 июня 2009

Я предполагаю, что причина, по которой вы хотите, чтобы другой элемент управления что-то сделал, заключается в том, что влажность влияет на некоторые другие свойства погоды / прогноза. В этом случае вы реализуете INotifyPropertyChanged, как и в ответе rmoore, и убедитесь, что при изменении влажности он либо явно изменяет другое свойство, вызывая обновление своего уведомления, либо отправляет уведомление о своем обновлении, например:

private int myHumidity;
            public int Humidity
            {
                    get
                    {
                            return this.myHumidity;
                    }
                    set
                    {
                            this.myHumidity = value;
                            NotifyPropertyChanged("Humidity");
                            NotifyPropertyChanged("MyOtherProperty");
                    }
            }
1 голос
/ 04 июня 2009

Значением по умолчанию для свойства UpdateSourceTrigger в привязке TextBox является «LostFocus»; единственное, что вам нужно сделать, это изменить это на PropertyChanged, тогда свойство Humidity будет отражать любые изменения при вводе их в TextBox.

Далее вы хотите убедиться, что ваш класс погоды реализует 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.

0 голосов
/ 04 июня 2009

Простой сценарий привязки будет примерно таким:

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();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...