[英]How to call events using CommunityToolkit.Mvvm
I am "attempting" to learn the MvvM architecture using C# within a WPF application.我正在“尝试”在 WPF 应用程序中使用 C# 学习 MvvM 架构。 I quickly realized that I was writing a tonne of duplication boilerplate thus I decided to install the NuGet CoummunityToolkit.Mvvm to handle the vast majority for me.
我很快意识到我正在编写大量的重复样板,因此我决定安装 NuGet CoummunityToolkit.Mvvm 来为我处理绝大多数。
I then started to create a very simple application which would just display items for me to learn the basics of MvvM.然后我开始创建一个非常简单的应用程序,它只显示项目让我学习 MvvM 的基础知识。 Therefore my View looks like such...
因此我的视图看起来像这样......
<UserControl.DataContext>
<viewmodel:DrawingMenuViewModel/>
</UserControl.DataContext>
<StackPanel>
<TextBox Text="{Binding SearchFilter}"/>
<DataGrid x:Name="ContactsResult"
ItemsSource="{Binding DrawingsCollectionView}"
SelectedItem="{Binding SelectedModel}"
AutoGenerateColumns="False" CanUserAddRows="False"
IsReadOnly="True" Height="300">
<DataGrid.Columns>
<DataGridTextColumn Header="DRAWING NO"
Binding="{Binding Path = DNumber}"/>
<DataGridTextColumn Header="DESCRIPTION"
Binding="{Binding Path = Description}"
Width="*"/>
<DataGridTextColumn Header="REV"
Binding="{Binding Path = Revision}"
Width="200"/>
</DataGrid.Columns>
</DataGrid>
<Button Content="Click" Command="{Binding OpenDrawingCommand}"/>
</StackPanel>
Then I started to rig up the backend ViewModel which works perfectly so far...然后我开始安装后端 ViewModel,到目前为止它工作得很好......
public partial class DrawingMenuViewModel : ObservableObject
{
public ObservableCollection<DrawingModel> _Drawings;
[ObservableProperty] ICollectionView drawingsCollectionView;
[ObservableProperty] DrawingModel selectedModel;
[ObservableProperty] string searchFilter = "D";
public DrawingMenuViewModel() => PopulateDatagrid();
#region Populating DataGrid
public void PopulateDatagrid()
{
// Initialize Data into the DataGrid Control
List<DrawingModel> testD = new List<DrawingModel>
{
new DrawingModel { DNumber = "D1294", Description = "Test 1", Revision = "A"},
new DrawingModel { DNumber = "D1295", Description = "Test 2", Revision = "A"},
new DrawingModel { DNumber = "D1296", Description = "Test 3", Revision = "A"},
new DrawingModel { DNumber = "D1297", Description = "Test 4", Revision = "A"},
};
// Hook-up data to view and set filter for search capability
_Drawings = new ObservableCollection<DrawingModel>(testD);
DrawingsCollectionView = CollectionViewSource.GetDefaultView(_Drawings);
DrawingsCollectionView.Filter = FilterDatagrid;
}
private bool FilterDatagrid(object obj)
{
if (obj is DrawingModel d)
{
return d.DNumber.Contains(searchFilter, StringComparison.OrdinalIgnoreCase) ||
d.Description.Contains(searchFilter, StringComparison.OrdinalIgnoreCase) ||
d.Revision.Contains(searchFilter, StringComparison.OrdinalIgnoreCase);
}
return false;
}
#endregion
[ICommand]
async Task OpenDrawing()
{
if (SelectedModel != null)
{
MessageBox.Show(SelectedModel.DNumber);
}
}
}
Where my issues begin is that I am struggling to understand how I can rig events such as a TextChanged event from the SearchFilter textbox which would run a command to filter the datagridview using the following statement...我的问题开始于我正在努力理解如何从 SearchFilter 文本框中装配诸如 TextChanged 事件之类的事件,该事件将运行命令以使用以下语句过滤 datagridview...
CollectionViewSource.GetDefaultView(DrawingsCollectionView).Refresh();
What I have tried without success is something like...我没有成功的尝试是这样的......
<TextBox Text="{Binding SearchFilter}" TextChanged="{Binding OpenDrawingCommand}"/>
Which results in error XLS0523 "Event 'TextChanged' can only be bound to properties of delegate type 'TextChangedEventHandler'.".这会导致错误 XLS0523“事件‘TextChanged’只能绑定到委托类型‘TextChangedEventHandler’的属性。”。 So I attempted to try calling the event like so...
所以我试图尝试像这样调用事件......
XAML
<TextBox Text="{Binding SearchFilter}" TextChanged="{Binding OpenDrawing}"/>
C#
public void OpenDrawing(object sender, TextChangedEventArgs e)
{
CollectionViewSource.GetDefaultView(DrawingsCollectionView).Refresh();
}
Resulting in the following error...导致以下错误...
System.Windows.Markup.XamlParseException: ''Provide value on 'System.Windows.Data.Binding' threw an exception.'
System.Windows.Markup.XamlParseException: ''在 'System.Windows.Data.Binding' 上提供值引发了异常。' Line number '15' and line position '48'.'
行号“15”和行位置“48”。
One solution is the use partial methods that are generated for just this purpose.一种解决方案是使用为此目的而生成的部分方法。
Here's what generally generated when you apply ObservableProperty
to a field.当您将
ObservableProperty
应用于字段时,通常会生成以下内容。
You can view this in the Project>Dependencies>Analyzers>CommunityToolkit.Mvvm.SourceGenerators
project node.您可以在
Project>Dependencies>Analyzers>CommunityToolkit.Mvvm.SourceGenerators
项目节点中查看此内容。
public string SearchFilter
{
get => searchFilter;
set
{
if (!EqualityComparer<string>.Default.Equals(searchFilter, value))
{
OnSearchFilterChanging(value);
OnPropertyChanging(new PropertyChangedEventArgs(nameof(SearchFilter)));
searchFilter = value;
OnSearchFilterChanged(value);
OnPropertyChanged(new PropertyChangedEventArgs(nameof(SearchFilter)));
}
}
}
partial void OnSearchFilterChanging(string value);
partial void OnSearchFilterChanged(string value);
You can learn more about partial methods here but the TLDR is that the implementation is left up to you but it's also not required that you implement it.您可以在此处了解有关部分方法的更多信息,但 TLDR 是由您决定实现,但也不需要您实现它。
All you need to do is implement the method and it will call those partial methods before and after the property changes.您需要做的就是实现该方法,它将在属性更改之前和之后调用这些部分方法。
If you type partial
then space, you will get intellisense for partial methods just like when you type override
.如果您键入
partial
then space,您将获得对部分方法的智能感知,就像您键入override
时一样。
partial void OnSearchFilterChanged(string value)
{
DrawingsCollectionView.Refresh();
}
You might also want to update your textbox binding to be more (but not too) responsive.您可能还想更新您的文本框绑定以更具响应性(但不是太)。
<TextBox Text="{Binding SearchFilter, UpdateSourceTrigger=PropertyChanged, Delay=250}"/>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.