如何通过 UserControl 的反序列化来获得视图模型的设计实例?

问题描述 投票:0回答:1

我有一个带有视图模型的用户控件:

public partial class FarmLogPageView : UserControl
{
    public FarmLogPage? ViewModel
    {
        get => (FarmLogPage)DataContext;
        set => DataContext = value;
    }

    public FarmLogPageView()
    {
        InitializeComponent();

        var dir = "D:\\_\\FolderQuantTests\\FarmLogPages\\";
        var files = Directory.EnumerateFiles(dir);
        string json = File.ReadAllText(files.First());
        ViewModel = JsonSerializer.Deserialize<FarmLogPage>(json);
    }
}

我还确保在 xaml 端定义了类型:

d:DataContext="{d:DesignInstance Type=diskManagerCore:FarmLogPage,
    IsDesignTimeCreatable=False}"

但是我的数据上下文是空的(根据构造函数后面的代码,我应该有一些东西)。我确保视图模型有一个无参数构造函数。

就好像我的构造函数后面的代码被忽略了。

如何根据文件中的序列化数据获得视图模型的设计实例?

PS 该测试通过(即,我有正确的类实例内容):

[TestMethod]
public void DeserializeTest()
{
    var dir = "D:\\_\\FolderQuantTests\\FarmLogPages\\";
    var file = Directory.EnumerateFiles(dir).First(o => o.Contains("Drive"));
    Console.WriteLine($"using {file}");

    string json = File.ReadAllText(file);
    var sut = JsonSerializer.Deserialize<FarmLogPage>(json);
    
    Assert.IsNotNull(sut);
    Assert.IsTrue(sut.ContentMap.Count > 0);
    Assert.AreEqual(28, sut.ContentMap.Count);
    //sut.ContentMap.ToCW();
}

全视图:

<UserControl x:Class="DiskManagerUI.FarmLogPageView"
             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:DiskManagerUI"
             xmlns:diskManagerCore="clr-namespace:DiskManagerCore;assembly=DiskManagerCore"
             d:DataContext="{d:DesignInstance Type=diskManagerCore:FarmLogPage, IsDesignTimeCreatable=False}"
             mc:Ignorable="d" 
             d:DesignHeight="450" d:DesignWidth="800">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="27"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>

        <StackPanel Grid.Row="0" Orientation="Horizontal">
            <StackPanel.Resources>

            </StackPanel.Resources>
            <TextBlock Text="{Binding PageType, FallbackValue=PageType}" Margin="0 0 10 0"/>
            <TextBlock Text="{Binding ErrorRate, FallbackValue=errorrate}" Margin="0 0 10 0"/>
            <TextBlock Text="{Binding Name, FallbackValue=name}" Margin="0 0 10 0"/>
        </StackPanel>

        <ListBox Grid.Row="1" ItemsSource="{Binding ContentMap}" BorderThickness="0" Background="AliceBlue">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <Border BorderBrush="Black" BorderThickness="1">
                        <StackPanel>
                            <TextBlock Text="{Binding Key}" />
                            <TextBlock Text="{Binding Value}" />
                        </StackPanel>
                    </Border>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>
    </Grid>
</UserControl>

背后代码:

using DiskManagerCore;
using System.IO;
using System.Text.Json;
using System.Windows.Controls;

namespace DiskManagerUI
{
    /// <summary>
    /// Interaction logic for FarmLogPageView.xaml
    /// </summary>
    public partial class FarmLogPageView : UserControl
    {
        public FarmLogPage? ViewModel
        {
            get => (FarmLogPage)DataContext;
            set => DataContext = value;
        }

        public FarmLogPageView()
        {
            InitializeComponent();

            var dir = "D:\\_\\FolderQuantTests\\FarmLogPages\\";
            var file = Directory.EnumerateFiles(dir).First(o => o.Contains("Drive"));
            string json = File.ReadAllText(file);
            ViewModel = JsonSerializer.Deserialize<FarmLogPage>(json);
        }
    }
}

视图模型:

[Serializable]
public class FarmLogPage
{
    protected string[] Content { get; set; }

    public string Name { get; set; }
    public FarmPageType PageType { get; set; }
    public bool HasContentMap { get; set; }
    public Dictionary<string, string> ContentMap { get; set; } = new();
    
    /// <summary>
    /// For tests or design
    /// </summary>
    public FarmLogPage()
    {
    }
}
c# wpf xaml
1个回答
0
投票

您不应该从构造函数中反序列化文件或遍历文件系统。这使得类型的实例化成为阻塞操作。这是代码的味道。

此外,将代码移到构造函数之外可以让您使用异步

JsonSerializer
API (
JsonSerializer.DeserializeAsync
),这将进一步提高性能。然后最好调用
JsonSerializer.Deserialize
的重载,它允许传入
Stream
(或文件路径)。让
JsonSerializer
处理该文件以使其能够提高性能。
File.ReadAllText
不是最好的选择。一般来说,更喜欢使用
StreamReader
来读取文件,因为它允许异步文件访问(例如
StreamReader.ReadAllAsync
)。

最后,您必须正确配置设计时数据。您必须将

IsDesignTimeCreatable
设置为
true
。否则,WPF 将创建一个假类型并且不会实例化原始类型(因此永远不会调用您的构造函数)。

d:DataContext="{d:DesignInstance Type=diskManagerCore:FarmLogPage, IsDesignTimeCreatable=True}"
© www.soinside.com 2019 - 2024. All rights reserved.