我有一个带有视图模型的用户控件:
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()
{
}
}
您不应该从构造函数中反序列化文件或遍历文件系统。这使得类型的实例化成为阻塞操作。这是代码的味道。
此外,将代码移到构造函数之外可以让您使用异步
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}"