簡體   English   中英

如何使用 CommunityToolkit.Mvvm 調用事件

[英]How to call events using CommunityToolkit.Mvvm

我正在“嘗試”在 WPF 應用程序中使用 C# 學習 MvvM 架構。 我很快意識到我正在編寫大量的重復樣板,因此我決定安裝 NuGet CoummunityToolkit.Mvvm 來為我處理絕大多數。

然后我開始創建一個非常簡單的應用程序,它只顯示項目讓我學習 MvvM 的基礎知識。 因此我的視圖看起來像這樣......

<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>

然后我開始安裝后端 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);
        }
    }
}

我的問題開始於我正在努力理解如何從 SearchFilter 文本框中裝配諸如 TextChanged 事件之類的事件,該事件將運行命令以使用以下語句過濾 datagridview...

CollectionViewSource.GetDefaultView(DrawingsCollectionView).Refresh(); 

我沒有成功的嘗試是這樣的......

<TextBox Text="{Binding SearchFilter}" TextChanged="{Binding OpenDrawingCommand}"/>

這會導致錯誤 XLS0523“事件‘TextChanged’只能綁定到委托類型‘TextChangedEventHandler’的屬性。”。 所以我試圖嘗試像這樣調用事件......

XAML
<TextBox Text="{Binding SearchFilter}" TextChanged="{Binding OpenDrawing}"/>

C#
public void OpenDrawing(object sender, TextChangedEventArgs e)
{
    CollectionViewSource.GetDefaultView(DrawingsCollectionView).Refresh();
}

導致以下錯誤...

System.Windows.Markup.XamlParseException: ''在 'System.Windows.Data.Binding' 上提供值引發了異常。' 行號“15”和行位置“48”。

一種解決方案是使用為此目的而生成的部分方法。

當您將ObservableProperty應用於字段時,通常會生成以下內容。

您可以在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);

您可以在此處了解有關部分方法的更多信息,但 TLDR 是由您決定實現,但也不需要您實現它。

您需要做的就是實現該方法,它將在屬性更改之前和之后調用這些部分方法。
如果您鍵入partial then space,您將獲得對部分方法的智能感知,就像您鍵入override時一樣。

partial void OnSearchFilterChanged(string value)
{
    DrawingsCollectionView.Refresh();
}

您可能還想更新您的文本框綁定以更具響應性(但不是太)。

<TextBox Text="{Binding SearchFilter, UpdateSourceTrigger=PropertyChanged, Delay=250}"/>

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM