gpt4 book ai didi

c# - 实现自己的 "Factory"以在 WPF 中重用 View

转载 作者:行者123 更新时间:2023-11-30 16:59:08 25 4
gpt4 key购买 nike

我目前正在使用 WAF (WPF Application Framework)用于 WPF 编程。我真的很喜欢为我的应用程序中的每个小 View 单元拥有一个自己的 View 模型的想法,我随后以这种方式实现了这一点。

在我的项目中,我得到了一个复杂的列表,其中每个列表元素还包含一个列表。由于复杂性,每个列表和列表列表元素都是一个自己的 ViewModel。 “最坏情况”场景总共包含 60-90 个 View 模型,仅用于 ListView 。

(这是一个问题列表,其中每个问题都有一个带有评分和其他 ui 元素的答案列表)。

此实现效果很好,但性能很差。分析后,我发现当我在一组问题之间切换时,错误会导致创建我的 ViewModel(因为必须再次生成整个列表)。

当我在问题集之间切换时,我无法 1:1 重复使用我的观点,因为问题数量不同。

但是,我认为我可以重用给定的 View 模型并在必要时添加(以防新集合需要更多 View )更多 View 模型。

因此我编写了以下工厂:

[Export]
public class ViewModelPerformanceFactory<T> where T : IPerformanceFactoryViewModel
{
private List<T> _collection;
private int _index;
private readonly ExportFactory<T> _exportFactory;

[ImportingConstructor]
public ViewModelPerformanceFactory(ExportFactory<T> exportFactory)
{
_exportFactory = exportFactory;
_index = 0;
}

public void Reset()
{
_index = 0;
if (_collection == null)
{
return;
}
foreach (var elem in _collection)
{
elem.Reset();
}
}

public T Get()
{
if (_collection == null)
{
_collection = new List<T>();
}
if (_collection.Count <= _index)
{
_collection.Add(_exportFactory.CreateExport().Value);
}
return _collection[_index++];
}
}

IPerformanceViewModel 只是提供了一个Reset 方法来清除 ViewModel 和 View。

所以每次加载新的问题集时,我都会调用我的 ViewModelPerformanceFactory 的重置函数,它会清除所有模型并将索引设置回 0(因此,如果有人需要一个新的 viewmodel 实例,它将获得第一个一个创建)。

从理论上讲,这很有效。

现在回答我的问题:我在问题集之间切换的次数越多,我的应用程序就越慢......这不是 View 模型对象的加载 - 这很好。我的列表看起来非常非常慢 - 有时甚至停滞几秒钟,然后继续增加......

我认为这是一个 WAF 问题,因为每个 ViewModel 都会实例化一个 View ,请参阅:

protected ViewModel(TView view) : base(view)
{
this.view = view;
}
}

而且我似乎无法像在 WAF 中重用 ViewModel 那样轻松地重用 View。

有没有人对我有建议或其他方法来加速我的申请?或者有人认为我的整个方法是愚蠢的并且我完全关闭停止编程吗? ;)

编辑:有时似乎存在内存/性能泄漏,但并非每次都可重现。:(

最佳答案

我不确定您的方法或为什么会出现性能问题,但这是我对类似问题的解决方案。

可以找到完整的解决方案 https://github.com/steinborge/ProxyTypeHelper/wiki

我想要实现的是创建“通用” View 模型的能力,然后可以将其分配给数据模板。数据模板只是一个用户控件。如果您有很多简单的数据维护屏幕,将节省大量重复代码。

但是有几个问题。数据模板在带有泛型的 XAML 中不能很好地工作,如果你有很多数据模板,你会创建很多 XAML - 特别是如果你想在单独的 View 中使用它。在您的情况下,您提到了多达 90 个 View - 这将是很多 XAML。

解决方案是将模板存储在查找中,并根据 DataContext 使用内容控件和 DataTemplateSelector 进行填充。所以首先需要注册数据模板/ View :

       manager.RegisterDataTemplate(typeof(GenericViewModel<CarType, WPFEventInter.ViewModel.CarTypeViewModel>), typeof(WPFEventInter.UserControls.CarTypesView));
manager.RegisterDataTemplate(typeof(GenericViewModel<Colour, WPFEventInter.ViewModel.ColourViewModel>), typeof(WPFEventInter.UserControls.ColourView));

RegisterDataTemplate 只是将数据模板添加到字典中:

   public void RegisterDataTemplate(Type viewModelType, Type dataTemplateType, string Tag="")
{
var template = BuildDataTemplate(viewModelType, dataTemplateType) ;
templates.Add(viewModelType.ToString() + Tag, template);
}

private DataTemplate BuildDataTemplate(Type viewModelType, Type viewType)
{
var template = new DataTemplate()
{
DataType = viewModelType,
VisualTree = new FrameworkElementFactory(viewType)
};

return template;
}

现在创建一个带有 ContentPresenter 控件的 View 。这将根据 View 的 Datacontext 显示 View 。

DataTemplateSelector 如下所示。这将根据数据上下文返回适当的 View :

public class ContentControlGenericTemplateSelector : DataTemplateSelector
{
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
DataTemplate retVal = null;
try
{
retVal = Core.WPF.Infrastructure.DataTemplateManager.templates[item.GetType().ToString()];
}
catch //empty catch to prevent design time errors..
{
}

return retVal;
}

关于c# - 实现自己的 "Factory"以在 WPF 中重用 View ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24271121/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com