将 ObservableCollection<class> 字段绑定到 ListBox DataTemplate
Binding ObservableCollection<class> fields to ListBox DataTemplate
我是一名刚刚结束暑期实习的学生,在开学前我带了一个项目回家做简单的工作。这个项目中有一个秒表,我宁愿使用一个绑定到我的列表框的 ObservableCollection 作为我的拆分时间,而不是使用 listbox.Items.Add()。当我添加到 ObservableCollection 时,ListBox UI 不会更新。谁能指出我错过了什么或做错了什么的正确方向?
我有我的 TimeSplits class:
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();
}
}
以及我页面中的 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);
}
...
}
和我的 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>
我确信这是一些我不知道的小东西,因为我今年夏天才开始学习数据绑定。任何帮助是极大的赞赏!提前致谢。
你的 nameof()
好像放错地方了。按照您当前代码的读取方式,它将始终发送 "propertyName" 的值作为更改的 属性 的名称,而不管 属性 实际更改了什么。
试试这个:
public int hours
{
get
{
return _hours;
}
set
{
_hours = value;
NotifyPropertyChanged();
}
}
然后,在您的 NotifyPropertyChanged()
中执行此操作:
private void NotifyPropertyChanged([CallerMemberName] string propertyName = "")
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName);
}
}
编辑:为以下内容添加了修复:
此外,ObservableCollection 必须是 属性。更改此代码:
public ObservableCollection<TimeSplits> splits = new ObservableCollection<TimeSplits>();
为此:
public ObservableCollection<TimeSplits> Splits { get; set; } = new ObservableCollection<TimeSplits>();
我从 Xamarin 的 ViewModel 模板中学到了一个对我帮助很大的技巧。这是它生成的代码,用于处理可观察的视图模型(很像 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
然后,要使用它,只需将其添加到您的属性中:
private string _title = string.Empty;
public string Title
{
get => _title;
set => SetProperty(ref _title, value);
}
我是一名刚刚结束暑期实习的学生,在开学前我带了一个项目回家做简单的工作。这个项目中有一个秒表,我宁愿使用一个绑定到我的列表框的 ObservableCollection 作为我的拆分时间,而不是使用 listbox.Items.Add()。当我添加到 ObservableCollection 时,ListBox UI 不会更新。谁能指出我错过了什么或做错了什么的正确方向?
我有我的 TimeSplits class:
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();
}
}
以及我页面中的 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);
}
...
}
和我的 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>
我确信这是一些我不知道的小东西,因为我今年夏天才开始学习数据绑定。任何帮助是极大的赞赏!提前致谢。
你的 nameof()
好像放错地方了。按照您当前代码的读取方式,它将始终发送 "propertyName" 的值作为更改的 属性 的名称,而不管 属性 实际更改了什么。
试试这个:
public int hours
{
get
{
return _hours;
}
set
{
_hours = value;
NotifyPropertyChanged();
}
}
然后,在您的 NotifyPropertyChanged()
中执行此操作:
private void NotifyPropertyChanged([CallerMemberName] string propertyName = "")
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName);
}
}
编辑:为以下内容添加了修复:
此外,ObservableCollection 必须是 属性。更改此代码:
public ObservableCollection<TimeSplits> splits = new ObservableCollection<TimeSplits>();
为此:
public ObservableCollection<TimeSplits> Splits { get; set; } = new ObservableCollection<TimeSplits>();
我从 Xamarin 的 ViewModel 模板中学到了一个对我帮助很大的技巧。这是它生成的代码,用于处理可观察的视图模型(很像 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
然后,要使用它,只需将其添加到您的属性中:
private string _title = string.Empty;
public string Title
{
get => _title;
set => SetProperty(ref _title, value);
}