OnPropertyChanged 不更新视图
OnPropertyChanged does not update the View
我有一个 ListView,它的项目源是 Elements,它是一个 Schranken 对象列表。 SchrankePresenter 是页面的 DataContext(在构造函数中设置)。
页面正确显示,直到单击一个按钮。如果单击一个按钮,按钮的名称值应该改变,ListView 应该多一个项目,但什么都没有 happens/updates。
这是 SchrankenPresenter:
public class SchrankePresenter : INotifyPropertyChanged
{
private List<Schranke> _elements;
public List<Schranke> Elements
{
get { return _elements; }
set
{
_elements = value;
OnPropertyChanged("Elements");
}
}
public ICommand ClickCommand { get; set; }
private void OnPropertyChanged(string propName)
{
Debug.WriteLine($"on Property changed with {propName}");
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName));
}
public event PropertyChangedEventHandler PropertyChanged;
public SchrankePresenter()
{
var elements = new List<Schranke>();
for (var i = 1; i < 15; i++)
elements.Add(new Schranke() { Name = $"{i}: Schranke" });
Elements = elements;
Debug.WriteLine("ctor");
ClickCommand = new DelegateCommand<Schranke>(ClickAction);
}
public void ClickAction(Schranke item)
{
VibrationDevice.GetDefault().Vibrate(TimeSpan.FromMilliseconds(150));
Debug.WriteLine($"{item?.Name} was clicked");
item.Name = "was clicked";
OnPropertyChanged("Name");
Elements.Add(new Schranke() { Name = "addednew element" });
OnPropertyChanged("Elements");
}
}
class Schranke 只有一名成员:public string Name { get; set; }
视图看起来像:
<ListView ItemsSource="{Binding Elements, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" x:Name="lv_schranken" Grid.Row="1" SelectedItem="{Binding SelectedItem}">
<ListView.ItemTemplate>
<DataTemplate>
<Button Height="80"
HorizontalAlignment="Stretch"
Command="{Binding ElementName=lv_schranken, Path=DataContext.ClickCommand}"
CommandParameter="{Binding}"
Style="{StaticResource TransparentStyle}">
<Grid>
.
. (some grid stuff)
.
<TextBlock Name="schranken_name"
Grid.Row="1"
Grid.Column="1"
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontWeight="ExtraLight"
FontSize="25"
Foreground="Black"
Text="{Binding Name, Mode=TwoWay}" />
</Grid>
</Button>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
PS:如果有人需要 DelegateCommand - 实现:
public class DelegateCommand<T> : ICommand
{
private Action<T> _clickAction;
public DelegateCommand(Action<T> clickAction)
{
_clickAction = clickAction;
}
public event EventHandler CanExecuteChanged;
public bool CanExecute(object parameter)
{
return true;
}
public void Execute(object parameter)
{
_clickAction((T)parameter);
}
}
如果你想绑定到项目列表,你应该绑定到 ObservableCollection
:
Represents a dynamic data collection that provides notifications when
items get added, removed, or when the whole list is refreshed.
https://msdn.microsoft.com/de-de/library/ms668604(v=vs.110).aspx
为了从 Viewmodel
更新 UI,我们需要提出 inotifypropertychanged
; observablecollection
默认提供 inotifypropertychanged
实现; .
我们可以参考 observablecollection
如果你想使用相同的列表,那么你需要在那个特定的列表上实现inotifypropertychanged
我有一个 ListView,它的项目源是 Elements,它是一个 Schranken 对象列表。 SchrankePresenter 是页面的 DataContext(在构造函数中设置)。
页面正确显示,直到单击一个按钮。如果单击一个按钮,按钮的名称值应该改变,ListView 应该多一个项目,但什么都没有 happens/updates。
这是 SchrankenPresenter:
public class SchrankePresenter : INotifyPropertyChanged
{
private List<Schranke> _elements;
public List<Schranke> Elements
{
get { return _elements; }
set
{
_elements = value;
OnPropertyChanged("Elements");
}
}
public ICommand ClickCommand { get; set; }
private void OnPropertyChanged(string propName)
{
Debug.WriteLine($"on Property changed with {propName}");
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName));
}
public event PropertyChangedEventHandler PropertyChanged;
public SchrankePresenter()
{
var elements = new List<Schranke>();
for (var i = 1; i < 15; i++)
elements.Add(new Schranke() { Name = $"{i}: Schranke" });
Elements = elements;
Debug.WriteLine("ctor");
ClickCommand = new DelegateCommand<Schranke>(ClickAction);
}
public void ClickAction(Schranke item)
{
VibrationDevice.GetDefault().Vibrate(TimeSpan.FromMilliseconds(150));
Debug.WriteLine($"{item?.Name} was clicked");
item.Name = "was clicked";
OnPropertyChanged("Name");
Elements.Add(new Schranke() { Name = "addednew element" });
OnPropertyChanged("Elements");
}
}
class Schranke 只有一名成员:public string Name { get; set; }
视图看起来像:
<ListView ItemsSource="{Binding Elements, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" x:Name="lv_schranken" Grid.Row="1" SelectedItem="{Binding SelectedItem}">
<ListView.ItemTemplate>
<DataTemplate>
<Button Height="80"
HorizontalAlignment="Stretch"
Command="{Binding ElementName=lv_schranken, Path=DataContext.ClickCommand}"
CommandParameter="{Binding}"
Style="{StaticResource TransparentStyle}">
<Grid>
.
. (some grid stuff)
.
<TextBlock Name="schranken_name"
Grid.Row="1"
Grid.Column="1"
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontWeight="ExtraLight"
FontSize="25"
Foreground="Black"
Text="{Binding Name, Mode=TwoWay}" />
</Grid>
</Button>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
PS:如果有人需要 DelegateCommand - 实现:
public class DelegateCommand<T> : ICommand
{
private Action<T> _clickAction;
public DelegateCommand(Action<T> clickAction)
{
_clickAction = clickAction;
}
public event EventHandler CanExecuteChanged;
public bool CanExecute(object parameter)
{
return true;
}
public void Execute(object parameter)
{
_clickAction((T)parameter);
}
}
如果你想绑定到项目列表,你应该绑定到 ObservableCollection
:
Represents a dynamic data collection that provides notifications when items get added, removed, or when the whole list is refreshed.
https://msdn.microsoft.com/de-de/library/ms668604(v=vs.110).aspx
为了从 Viewmodel
更新 UI,我们需要提出 inotifypropertychanged
; observablecollection
默认提供 inotifypropertychanged
实现;
observablecollection
如果你想使用相同的列表,那么你需要在那个特定的列表上实现inotifypropertychanged