XAML 从存储区获取值后视图未更新

xt0899hw  于 2023-09-28  发布在  其他
关注(0)|答案(1)|浏览(112)

在我的MVVM应用程序中,当我使用静态方法创建视图模型以从商店加载数据并获得通知时,当通知从商店到达时,视图不会更新。商店使用Lazy类。
当我第一次加载视图模型时会发生什么,首先调用静态视图模型构造器,然后调用OnCodeTypesLoaded。但是当我在视图模型之间切换时,视图会正确显示,就像预期的那样。我发现的一个解决方案是在XAML绑定中将IsAsync设置为true,然而,我认为这不是一个好的解决方案,因为它看起来很不稳定。我有视图模型的OnPropertyChanged属性。
依赖性注入

services.AddSingleton<CreateViewModel<ProductViewModel>>(services => () => CreateProductViewModel(services));

private static ProductViewModel CreateProductViewModel(IServiceProvider services)
{
    return ProductViewModel.LoadProduct(services.GetRequiredService<IProductEndpoint>(),services.GetRequiredService<ICodeTypesStore>());
}

产品视图模型

public class ProductViewModel : ViewModelBase
{
    private readonly IProductEndpoint _productEndpoint;
    private readonly ICodeTypesStore _codeTypesStore;

    public ProductViewModel(IProductEndpoint productEndpoint, ICodeTypesStore codeTypesStore)
    {
        _productEndpoint = productEndpoint;
        _codeTypesStore = codeTypesStore;
        _codeTypesStore.CodeTypesLoaded += OnCodeTypesLoaded;

        LoadProductCommand = new LoadProductCommand(this, productEndpoint);
        LoadCodeTypesCommand = new LoadCodeTypesCommand(codeTypesStore);
    }
    private void OnCodeTypesLoaded()
    {
        SystemTypes = _codeTypesStore.SystemTypes(SistemTypes.IT_Management);
        Product.SetNonExistantIdentifiers(SystemTypes);
    }
    public ICommand LoadProductCommand { get; }
    public ICommand LoadCodeTypesCommand { get; }
    
    public static ProductViewModel LoadProduct(IProductEndpoint productEndpoint, ICodeTypesStore codeTypesStore)
    {
        ProductViewModel viewModel = new ProductViewModel(productEndpoint,codeTypesStore);
        
        viewModel.LoadProductCommand.Execute(null);
        viewModel.LoadCodeTypesCommand.Execute(null);
        return viewModel;
    }
}

显示产品类别

public class DisplayProduct : UI.Product
{
    public DisplayProduct(){}

    private List<UI.Sistem> _systems;
    public List<UI.Sistem> NonExistantIdentifiers { get; private set; }

    public DisplayProduct(UI.Product prd): base(prd.ID,prd.Name,prd.IsCompra,prd.IsProducao,prd.IsVenda,prd.Identifiers)
    {
    }
    
    public void SetNonExistantIdentifiers(List<UI.Sistem> systems)
    {
        _systems = systems;

        SetNonExistantIdentifiers();
    }
    private void SetNonExistantIdentifiers()
    {
        NonExistantIdentifiers = _systems.Where(s => !base.Identifiers.Select(x => x.System.ID).ToList().Contains(s.ID)).ToList();
    }

}

用户控制产品未加载

<UserControl x:Class="WPFStuff.Controls.ProductIDsNonLoaded"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
         xmlns:local="clr-namespace:WPFStuff.Controls"
         xmlns:helpers="clr-namespace:WPFStuff.Helpers"
         mc:Ignorable="d" 
         d:DesignHeight="450" d:DesignWidth="800">

<ItemsControl ItemsSource="{Binding NonExistantIdentifiers}">
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <WrapPanel>

                <Grid>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="Auto" SharedSizeGroup="Label"/>
                    </Grid.ColumnDefinitions>

                    <TextBlock Text="{Binding Name}"/>
                </Grid>

                <Grid>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="Auto" SharedSizeGroup="Value"/>
                    </Grid.ColumnDefinitions>

                    <TextBox MinWidth="150" helpers:SelectAllFocusBehavior.Enable="True">
                        <TextBox.Resources>
                            <helpers:BindingProxy x:Key="TargetProxy2" Data="{Binding RegExpression}"/>
                        </TextBox.Resources>
                        <TextBox.Text>
                            <Binding Path="Name" UpdateSourceTrigger="PropertyChanged">
                                <Binding.ValidationRules>
                                    <helpers:CodeTypeValidationRule>
                                        <helpers:CodeTypeValidationRule.CodeTypePattern>
                                            <helpers:CodeTypeValidationParameter RegExPattern="{Binding Data, Source={StaticResource TargetProxy2}}"/>
                                        </helpers:CodeTypeValidationRule.CodeTypePattern>
                                    </helpers:CodeTypeValidationRule>
                                </Binding.ValidationRules>
                            </Binding>
                        </TextBox.Text>
                    </TextBox>

                </Grid>
            </WrapPanel>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

ProductView

<UserControl x:Class="WPFStuff.Views.ProductView"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
         xmlns:local="clr-namespace:WPFStuff.Views"
         xmlns:controls="clr-namespace:WPFStuff.Controls" xmlns:helpers="clr-namespace:WPFStuff.Helpers"
         mc:Ignorable="d"
         FontSize="20"
         d:DesignHeight="450" d:DesignWidth="800">
<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="Auto"/>
    </Grid.ColumnDefinitions>

    <Grid.RowDefinitions>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="Auto"/>
    </Grid.RowDefinitions>
    
    <controls:Product DataContext="{Binding Product}" />

    <WrapPanel Grid.IsSharedSizeScope="True" Grid.Row="1">
        <controls:ProductsIDs DataContext="{Binding Product}"  />
        <controls:ProductIDsNonLoaded DataContext="{Binding Product}"/>
    </WrapPanel>
    
</Grid>

CodeTypesStore

public class CodeTypesStore : ICodeTypesStore
{
    private readonly ICodeTypesEndpoint _codeTypesEndpoint;
    private readonly List<UI.Sistem> _systemCodeTypes;
    private readonly List<UI.CodeType> _productCodeTypes;

    private Lazy<Task> _loadCodeTypesLazy;

    public event Action CodeTypesLoaded;

    public CodeTypesStore(ICodeTypesEndpoint codeTypesEndpoint)
    {
        _codeTypesEndpoint = codeTypesEndpoint;
        _productCodeTypes = new();
        _systemCodeTypes = new();

        _loadCodeTypesLazy = CreateLoadCodeTypes();
    }
    private bool _isLoading;

    public bool IsLoading
    {
        get { return _isLoading; }
        set { _isLoading = value; }
    }

    public async Task LoadCodeTypes()
    {
        await _loadCodeTypesLazy.Value;
        CodeTypesLoaded?.Invoke();
    }

    private Lazy<Task> CreateLoadCodeTypes()
    {
        return new Lazy<Task>(() => InitializeCodeTypes());
    }

    private async Task InitializeCodeTypes()
    {
        IEnumerable<UI.Sistem> s = await _codeTypesEndpoint.GetSystemTypesCodes();
        IEnumerable<UI.CodeType> c = await _codeTypesEndpoint.GetProductsCodeTypes();

        _systemCodeTypes.Clear();
        _productCodeTypes.Clear();

        _systemCodeTypes.AddRange(s);
        _productCodeTypes.AddRange(c);

        //CodeTypesLoaded?.Invoke();
    }

    public List<UI.Sistem> SystemTypes(SistemTypes systemTypes)
    {
        return _systemCodeTypes.Where(sct => sct.SystemType?.SystemTypes == systemTypes).ToList();
    }
    public IEnumerable<UI.CodeType> ProductCodeTypes => _productCodeTypes;

}
gdx19jrr

gdx19jrr1#

我解决了这个问题,我在DisplayProduct类中将List更改为ObservableCollection

public DisplayProduct(){}

    private ObservableCollection<UI.Sistem> _nonExistantIdentifiers = new ObservableCollection<UI.Sistem>();
    public ObservableCollection<UI.Sistem> NonExistantIdentifiers 
    {
        get
        {
            return _nonExistantIdentifiers;
        }
        private set
        {
            _nonExistantIdentifiers = value;
        }
    }
       

    public DisplayProduct(UI.Product prd): base(prd.ID,prd.Name,prd.IsCompra,prd.IsProducao,prd.IsVenda,prd.Identifiers)
    {
    }
    public void SetNonExistantIdentifiers(List<UI.Sistem> systems)
    {
        var nonExistantIDs = systems.Where(s => !base.Identifiers.Select(x => x.System.ID).ToList().Contains(s.ID)).ToList();

        foreach (var item in nonExistantIDs)
        {
            _nonExistantIdentifiers.Add(item);
        }

        NonExistantIdentifiers = _nonExistantIdentifiers;
    }
}

相关问题