我正在尝试构建这个简单的UWP MVVM注释应用程序。
当点击 添加 Textbox
或删除时,该应用的目的是将文字从ListView
添加到Button
按 删除 ListView
的{{1}}项,该项目已分配给Button
中的每个项目。
向ListView
添加项目似乎工作正常。这些项目显示在ObservableCollection<Note>
中,没有任何问题。
删除项目并不能正常工作。
我尝试调用负责从构造函数和 删除 ListView
中删除项目的方法。
当我从 删除 Button
调用DoDeleteNote(Note itemToDelete)
时,没有任何反应,但如果我从构造函数中调用相同的方法,则该项目将被删除。
我在Button
方法中创建了一个断点,我可以在调试器中看到它贯穿代码,但没有从DoDeleteNote(Note itemToDelete)
中删除任何内容。
但是,当我从构造函数中调用ObservableCollection<Note>
方法时,项目将被删除。
同样奇怪的是,我创建的 Note 项目以及从 NoteViewModel 构造函数添加到DoDeleteNote(Note itemToDelete)
的项目是{ {1}}。我使用 添加 ObservableCollection<Note>
添加的项目已消失,但仍显示在ObservableCollection<Note>
。
我想也许Button
或绑定可能有问题,但我不知道从哪里开始寻找,以及寻找什么,所以我可以使用一些帮助。
我知道这里似乎有很多代码,但我觉得有必要不要忽略任何东西来理解数据流。
ListView
INotifyPropertyChanged
<Page
x:Class="ListView2.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:ListView2"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:viewModel="using:ListView2.ViewModel"
mc:Ignorable="d">
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Grid.DataContext>
<viewModel:NoteViewModel/>
</Grid.DataContext>
<ListView Header="Notes"
HorizontalAlignment="Left"
Height="341"
Width="228"
VerticalAlignment="Top"
Margin="163,208,0,0"
ItemsSource="{Binding Notes, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
<ListView.ItemTemplate>
<DataTemplate x:Name="MyDataTemplate">
<StackPanel Orientation="Horizontal">
<TextBlock x:Name="TbxblListItem" Text="{Binding NoteText}"/>
<Button Command="{Binding DeleteNoteCommand}"
CommandParameter="{Binding ElementName=TbxblListItem}">
<Button.DataContext>
<viewModel:NoteViewModel/>
</Button.DataContext>
<Button.Content>
<SymbolIcon Symbol="Delete"
ToolTipService.ToolTip="Delete Note"
HorizontalAlignment="Center"
VerticalAlignment="Center"/>
</Button.Content>
</Button>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<TextBox x:Name="TbxNoteContent" HorizontalAlignment="Left"
Margin="571,147,0,0"
TextWrapping="Wrap"
VerticalAlignment="Top"
Width="376"/>
<Button Content="Add"
HorizontalAlignment="Left"
Margin="597,249,0,0"
VerticalAlignment="Top"
Command="{Binding AddNoteCommand}"
CommandParameter="{Binding Text, ElementName=TbxNoteContent}"/>
</Grid>
</page>
namespace ListView2.Model
{
class Note
{
private string _noteText;
public Note(string noteText)
{
NoteText = noteText;
}
public string NoteText { get { return _noteText; } set { _noteText = value; } }
}
}
作为ICommand的实现的RelayCommand类似乎与这个问题无关,所以我没有把它包含在这里,但如果你好奇,可以在GitHub上看到
答案 0 :(得分:1)
正如@Eugene Podskal指出的一个问题是这个代码
<Button.DataContext>
<viewModel:NoteViewModel/>
</Button.DataContext>
您的布局网格实例化一个新的NoteViewModel
,上面的代码将执行相同的操作,让您在页面上激活2个NoteViewModel。
首先给ListView一个名字
<ListView x:Name="MyList" Header="Notes"
接下来,让我们修复ListView DataTemplate
的{{1}}上的绑定
MyList
这一行
<ListView.ItemTemplate>
<DataTemplate x:Name="MyDataTemplate">
<StackPanel Orientation="Horizontal">
<TextBlock x:Name="TbxblListItem" Text="{Binding NoteText}"/>
<Button Command="{Binding DataContext.DeleteNoteCommand, ElementName=MyList}"
CommandParameter="{Binding}">
<SymbolIcon Symbol="Delete"
ToolTipService.ToolTip="Delete Note"
HorizontalAlignment="Center"
VerticalAlignment="Center"/>
</Button>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
表示我们现在绑定到Command="{Binding DataContext.DeleteNoteCommand, ElementName=MyList}"
的{{1}} DataContext
,这是MyList
NoteViewModel
Grid
简化为
CommandParamter
正如我在下面解释的那样,更好的做法是绑定到CommandParameter="{Binding}"
中的对象,在这种情况下是MyList
的对象
为了完成这项工作,我们需要稍微调整您的Note
将您的私人删除字段和公共属性更改为
NoteViewModel
并在构造函数中
private RelayCommand<Note> _deleteNoteCommand;
public RelayCommand<Note> DeleteNoteCommand { get { return _deleteNoteCommand; } set { _deleteNoteCommand = value; } }
DeleteNoteCommand = new RelayCommand<Note>(DoDeleteNote);
方法简化为
DoDeleteNote
所以我们轻而易举地摆脱private void DoDeleteNote(Note note)
{
this.Notes.Remove(note);
}
的施法。您现在可以摆脱TextBlock
方法,因为它不再需要。
最后,我们需要添加一个新的DeleteNote
,它采用通用类型来使我们的命令RelayCommand
正常工作。
<强> RelayCommand 强>
DeleteNoteCommand
道歉这个答案很长,但我想指出每一步。我还建议在使用xaml时使用mvvm框架,因为它会让你的生活更轻松。我推荐mvvmlight,但还有很多其他的。希望有所帮助