Не могу получить двухстороннее связывание из Xaml в ObservableCollection Working

Я пытаюсь привязать gridView к ObservableCollection в приложении Магазина Windows. Моя проблема в том, что я получаю данные, но набор не работает

public class ValveData : INotifyPropertyChanged
{
    private string valveName;
    private decimal waterMl;
    private decimal waterEc;
    private decimal waterPh;


    public string ValveName 
    {
        get { return this.valveName; }
        set
        {
            this.valveName = value;
            this.OnPropertyChanged("ValveName");
        }
    }

    public decimal WaterMl
    {
        get { return this.waterMl; }
        set
        {
            this.waterMl = value;
            this.OnPropertyChanged("WaterMl");
        }
    }

    public decimal WaterEc
    {
        get { return this.waterEc; }
        set
        {
            this.waterEc = value;
            this.OnPropertyChanged("WaterEc"); 
        }
    }

    public decimal WaterPh
    {
        get { return this.waterPh; }
        set
        {
            this.waterPh = value;
            this.OnPropertyChanged("WaterPh");
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    public void OnPropertyChanged(string propertyName)
    {
        if (this.PropertyChanged != null)
        {
            this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

public class ValveDataCollection : ObservableCollection<ValveData>
{
    public ValveDataCollection() : base()
    {
        Add(new ValveData { ValveName = "Valve 1", WaterMl = 100, WaterEc = 3, WaterPh = 5 });
        Add(new ValveData { ValveName = "Valve 2" });
        Add(new ValveData { ValveName = "Valve 3" });
        Add(new ValveData { ValveName = "Valve 4" });
    }
}

а это мой хамл

<data:ValveDataCollection x:Key="ValvesData"/>

<GridView x:Name="gw1" Grid.Row="2" ItemsSource="{StaticResource ValvesData}">
        <GridView.ItemTemplate>
            <DataTemplate>
                <StackPanel>
                    <TextBox Text="{Binding ValveName, Mode=TwoWay}"/>
                    <TextBox Text="{Binding WaterMl, Mode=TwoWay}"/>
                    <TextBox Text="{Binding WaterEc, Mode=TwoWay}"/>
                    <TextBox Text="{Binding WaterPh, Mode=TwoWay}"/>
                </StackPanel>
            </DataTemplate>
        </GridView.ItemTemplate>
</GridView>

Я уверен, что что-то упустил, но я искал этот код в течение нескольких дней и не могу понять его. Строка выглядит так, как будто она работает, то есть, если у меня есть 2 текстовых поля, связанных с ValveName String, установите строку и получите данные, но похоже, он не работает для десятичных чисел, они получают данные при запуске, но если вы измените их в текстовом поле, это, похоже, не повлияет на переменную

1 ответ

Решение

Правильный XAML должен выглядеть

<TextBox Text="{Binding ValveName, Mode=TwoWay}"/>

скорее, чем

<TextBox Text="{Binding ValveName}, Mode=TwoWay"/>

Изменить на заметку:

Этот код не является потокобезопасным. Между this.PropertyChanged != null а также this.PropertyChanged другая ветка может отписаться и PropertyChanged становится null,

public void OnPropertyChanged(string propertyName)
{
    if (this.PropertyChanged != null)
    {
        this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
}

Всегда используйте локальную копию обработчика событий!

public void OnPropertyChanged(string propertyName)
{
    var handler = this.PropertyChanged;
    if (handler != null)
    {
        handler(this, new PropertyChangedEventArgs(propertyName));
    }
}

Этот поток теперь безопасен

Для будущих читателей: С C# 6.0 (Visual Studio 2015) вы также можете использовать приведенную ниже версию, которая короче и потокобезопасна, используя новый оператор "Null Propagation Operator".

public void OnPropertyChanged(string propertyName)
{
    this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
Другие вопросы по тегам