简体   繁体   English

绑定ObservableCollection <class> ListBox DataTemplate的字段

[英]Binding ObservableCollection<class> fields to ListBox DataTemplate

I am a student that just finished up a summer internship, and I brought home a project to work on briefly before school starts up. 我是一名刚刚完成暑期实习的学生,在学校开学之前,我带回了一个正在进行的项目。 This project has a stopwatch in it, and I would rather use an ObservableCollection bound to my ListBox for my split times, rather that using the listbox.Items.Add(). 这个项目中有一个秒表,我宁愿使用绑定到ListBox的ObservableCollection作为我的拆分时间,而不是使用listbox.Items.Add()。 When I add to the ObservableCollection, the ListBox UI does not update. 当我添加到ObservableCollection时,ListBox UI不会更新。 Could anyone point me in the right direction on what I missed or what I did wrong? 任何人都可以针对我错过的内容或做错的事情为我指明正确的方向吗?

I have my TimeSplits class: 我有TimeSplits课程:

public class TimeSplits : INotifyPropertyChanged
{

    private int _hours;
    private int _minutes;
    private int _seconds;

    public int hours
    {
        get
        {
            return _hours;
        }
        set
        {
            _hours = value;
            NotifyPropertyChanged(hours);
        }
    }
    public int minutes
    {
        get
        {
            return _minutes;
        }
        set
        {
            _minutes = value;
            NotifyPropertyChanged(minutes);
        }
    }
    public int seconds
    {
        get
        {
            return _seconds;
        }
        set
        {
            _seconds = value;
            NotifyPropertyChanged(seconds);
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    private void NotifyPropertyChanged(int propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(nameof(propertyName)));
        }
    }

    public override string ToString()
    {
        return hours.ToString() + ":" + minutes.ToString() + ":" + seconds.ToString();
    }
}

and my ObservableCollection in my Page: 和我的Page中的ObservableCollection:

public partial class StopwatchPage : Page , INotifyPropertyChanged
{
...
    public ObservableCollection<TimeSplits> splits = new ObservableCollection<TimeSplits>();
...
    public StopwatchPage()
    {
        DataContext = this;
        InitializeComponent();
        timer.Interval = TimeSpan.FromSeconds(1);
        timer.Tick += new EventHandler(stopwatchTimer);
    }
...
    private void splitButton_Click(object sender, RoutedEventArgs e)
    {
        TimeSplits split = new TimeSplits();
        split.hours = Hours;
        split.minutes = Minutes;
        split.seconds = Seconds;
        splits.Add(split);
    }
...
}

and my xaml: 和我的xaml:

<ListBox x:Name="newSplitListBox" HorizontalAlignment="Left" Margin="139,0,0,47" Width="185" Height="268" VerticalAlignment="Bottom" ItemsSource="{Binding splits}">
        <ListBox.ItemTemplate>
            <DataTemplate>
                <StackPanel Orientation="Horizontal">
                    <TextBlock Text="{Binding hours}"/>
                    <TextBlock Text="{Binding minutes}"/>
                    <TextBlock Text="{Binding seconds}"/>
                </StackPanel>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>

I am sure it is something small that I have no clue about, as I just started learning data binding this summer. 我敢肯定,这是我所不知道的小事情,因为我今年夏天才开始学习数据绑定。 Any help is greatly appreciated! 任何帮助是极大的赞赏! Thanks in advance. 提前致谢。

It looks like you have nameof() in the wrong place. 看来您在错误的位置输入了nameof() The way your current code reads, it will always send the value of "propertyName" as the name of the property that changed, regardless of what property actually changed. 当前代码的读取方式将始终发送“ propertyName”的值作为已更改属性的名称,而不管实际更改了哪个属性。

Try this: 尝试这个:

public int hours
{
    get
    {
        return _hours;
    }
    set
    {
        _hours = value;
        NotifyPropertyChanged();
    }
}

Then, in your NotifyPropertyChanged() , do this: 然后,在您的NotifyPropertyChanged() ,执行以下操作:

private void NotifyPropertyChanged([CallerMemberName] string propertyName = "")
{
    if (PropertyChanged != null)
    {
        PropertyChanged(this, new PropertyChangedEventArgs(propertyName);
    }
}

Edit: Added fix for the following: 编辑:添加了以下修复程序:

Also, the ObservableCollection needs to be a property. 另外,ObservableCollection必须是一个属性。 Change this code: 更改此代码:

public ObservableCollection<TimeSplits> splits = new ObservableCollection<TimeSplits>();

To this: 对此:

public ObservableCollection<TimeSplits> Splits { get; set; } = new ObservableCollection<TimeSplits>();

I learned a trick from Xamarin's ViewModel template that helped me immensely. 我从Xamarin的ViewModel模板中学到了一个技巧,极大地帮助了我。 Here is the code that it generates that handles an observable View Model (much like the ObservableCollection). 这是它生成的用于处理可观察视图模型(类似于ObservableCollection)的代码。

    protected bool SetProperty<T>(ref T backingStore, T value,
        Action onChanged = null,
        [CallerMemberName]string propertyName = "")
    {
        if (EqualityComparer<T>.Default.Equals(backingStore, value))
            return false;

        backingStore = value;
        onChanged?.Invoke();
        OnPropertyChanged(propertyName);
        return true;
    }

    #region INotifyPropertyChanged
    public event PropertyChangedEventHandler PropertyChanged;
    protected void OnPropertyChanged([CallerMemberName] string propertyName = "")
    {
        var changed = PropertyChanged;
        if (changed == null)
            return;

        changed.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
    #endregion

Then, to use this, simply add this to your properties: 然后,要使用此功能,只需将其添加到您的属性中:

private string _title = string.Empty;
public string Title
{
    get => _title;
    set => SetProperty(ref _title, value);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM