簡體   English   中英

當綁定的 ObservableCollection 更改時,來自 CommunityToolkit.WinUI.Controls.DataGrid 的 DataGrid 不更新

[英]DataGrid from CommunityToolkit.WinUI.Controls.DataGrid not updating when bound ObservableCollection changes

我有一個包含三個過濾器選項的下拉列表:全部、活動和非活動。 更改所選值會引發一個事件,該事件會調整 ViewModel 中的可觀察集合屬性ProjectDbUsers ,顯示應用程序用戶的 Datagrid 綁定到該屬性。 當我調試時,代碼成功更改了ProjectDbUsers屬性,但 Datagrid 未刷新/更新以匹配更改后的 object 集合。

注意:我在主 UI 項目中使用CommunityToolkit.WinUI.Controls.DataGrid package,在包含 ViewModel 的業務層項目中使用CommunityToolkit.Mvvm package。

代碼:

在Manage Users頁面XAML,顯示Combobox和Datagrid:

        <ComboBox x:Name="BasicUserFilter"  Grid.Row="0" Grid.Column="1"
                   Height="30" Width="Auto" Margin="20,10,10,10"
                  ItemsSource="{x:Bind ViewModel.Filters, Mode=OneWay}" 
                  SelectedItem="{x:Bind ViewModel.SelectedFilter, Mode=TwoWay}"                      
                  SelectionChanged="BasicUserFilter_SelectionChanged"/>

<controls:DataGrid x:Name="dataGrid1" Grid.Row="2"
Height="600" Margin="12"
AutoGenerateColumns="False"
ItemsSource="{x:Bind ViewModel.ProjectDbUsers, Mode=OneWay}">
    <controls:DataGrid.Columns>
        <controls:DataGridTextColumn 
            Header="Name" 
            Width="250"
            Binding="{Binding UserAddisplayName}" 
            FontSize="14" />
            ...
    </controls:DataGrid.Columns>
</controls:DataGrid> 

更改過濾器 Combobox 值時觸發BasicUserFilter_SelectionChanged事件的隱藏代碼。

private void BasicUserFilter_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    ViewModel.UpdateGridBasedOnFilter();
}

ViewModel class 的摘錄,顯示了綁定的屬性定義和過濾器下拉選擇發生變化時調用的方法:

[ObservableProperty]
private string _selectedFilter;   

public ObservableCollection<string> Filters { get; } = new ObservableCollection<string>(new List<string>() { "All", "Active", "Inactive" });

public ObservableCollection<UserAd> ProjectDbUsers { get; private set; }

public void UpdateGridBasedOnFilter()
{
    using (UnitOfWorkDbGlobal unitOfWorkDbGlobal = new(new MyDBContext()))
    {
        List<UserAd> users = new();
        switch (SelectedFilter)
        {
            case "All":
                users = unitOfWorkDbGlobal.UserAds.GetAllUsers().ToList();
                break;
            case "Active":
                users = unitOfWorkDbGlobal.UserAds.GetAllActiveUsers().ToList();
                break;
            case "Inactive":
                users = unitOfWorkDbGlobal.UserAds.GetAllInactiveUsers().ToList();
                break;
        }

        ProjectDbUsers = new ObservableCollection<UserAd>(users);
    }
}

為了在ProjectDbUsers更改時允許 Datagrid 更新,可能缺少什么?

由於您要重新實例化 projectDbUsers 屬性本身,因此需要將其設為 ObservableProperty。

與您的問題沒有直接關系,但您可以使用CommunityToolkit.Mvvm生成的partial方法,而不是在代碼隱藏中調用BasicUserFilter_SelectionChanged()

請參閱此示例代碼。

using CommunityToolkit.Mvvm.ComponentModel;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;

namespace DataGridTest;

public enum Filters
{
    All,
    Active,
    Inactive,
}

public class UserAd
{
    public string Name { get; set; } = string.Empty;
}

public partial class MainPageViewModel : ObservableObject
{
    private List<UserAd> userAdSource = new()
    {
        new UserAd() { Name = "User A - Active" },
        new UserAd() { Name = "User B - Inactive" },
        new UserAd() { Name = "User C - Active" },
        new UserAd() { Name = "User D - Inactive" },
        new UserAd() { Name = "User E - Active" },
    };

    // The CommunityToolkit.Mvvm auto-generates 
    // partial void OnSelectedFilterChanged(Filters value).
    [ObservableProperty]
    private Filters selectedFilter = Filters.All;

    // ObservableCollections notifies the UI when you add/remove elements.
    // Since you are reinstantiating the projectDbUsers property itself, 
    // you need to make it ObservableProperty.
    //public ObservableCollection<UserAd> ProjectDbUsers { get; set; }
    [ObservableProperty]
    private ObservableCollection<UserAd>? projectDbUsers;

    public MainPageViewModel()
    {
        IEnumerable<UserAd> filteredUserAds = GetFilteredUserAds(SelectedFilter);
        ProjectDbUsers = new ObservableCollection<UserAd>(filteredUserAds);
    }

    public List<Filters> FilterList { get; } = new(Enum.GetValues<Filters>());

    // This "partial method" is auto-generated by the CommunityTookit.Mvvm.
    async partial void OnSelectedFilterChanged(Filters value)
    {
        IEnumerable<UserAd> filteredUserAds = await GetFilteredUserAds(value);
        ProjectDbUsers = new ObservableCollection<UserAd>(filteredUserAds);
    }

    private Task<IEnumerable<UserAd>> GetFilteredUserAds(Filters filter)
    {
        return await Task.Run(() =>
        {
            return filter is Filters.All
                ? this.userAdSource
                : this.userAdSource.Where(x => x.Name.Contains(filter.ToString()));
        });
    }
}

主頁.xaml

<Page
    x:Class="DataGridTest.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:controls="using:CommunityToolkit.WinUI.UI.Controls"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:local="using:DataGridTest"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
    mc:Ignorable="d">

    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>

        <ComboBox
            Grid.Row="0"
            ItemsSource="{x:Bind ViewModel.FilterList}"
            SelectedItem="{x:Bind ViewModel.SelectedFilter, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />

        <controls:DataGrid
            Grid.Row="1"
            AutoGenerateColumns="False"
            ItemsSource="{x:Bind ViewModel.ProjectDbUsers, Mode=OneWay}">
            <controls:DataGrid.Columns>
                <controls:DataGridTextColumn
                    Width="250"
                    Binding="{Binding Name}"
                    FontSize="14"
                    Header="Name" />
            </controls:DataGrid.Columns>
        </controls:DataGrid>
    </Grid>
</Page>

暫無
暫無

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

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