kux*_*kux 7 controltemplate maui
如何使用绑定和 DataTemplate 呈现字符串、数字或视图模型?
我正在寻找 WPF ContentControl 的 MAUI 替代品。
具有ContentViewContent 属性,但这是来自 type View。具有ContentPresenterContent 属性,但这也来自 type View。<Ignorable>WTF,为什么它只能呈现一个视图,而不被命名为 ViewPresenter ???有时 MAUI 很奇怪。</Ignorable>
如何通过为每种数据类型定义数据模板来呈现任何内容?
class PropertyViewModel {
public string Name {get;set;}
public object Value {get;set;}
}
Run Code Online (Sandbox Code Playgroud)
<Page.Resources>
<DataTemplate DataType="System.String">
<Entry Text="{Binding}/>
</DataTemplate>
<DataTemplate DataType="System.Int32">
<NumberPicker Value="{Binding}/>
</DataTemplate>
.. more templates, eg. DatePicker for System.DateOnly
</Page.Resources>
<DockLayout>
<Label Text="{Binding Name}
<TemplatedContenView Content={Binding Value}/>
</DockPanel>
Run Code Online (Sandbox Code Playgroud)
TemplatedContenView 或 ContentControl(MAUI 中不存在)可以对不同类型的值使用不同的模板。在 WPF 中,ContentControl 使用 ContentTemplate、ContentTemplateSelector,或者如果未指定,则它会查找资源来查找模板。
<Ignorable>对于 MAUI,我经常有一种感觉,我必须不断地重新发明 WPF 中的标准东西。是的,我知道 MAUI 不是 WPF,但至少应该有类似的概念。从 WinForms 到 WPF 的转换要容易得多,而且差异也相当大。</Ignorable>
Edit1:更详细的示例
我是一名 WPF 开发人员,最近我开始了 MAUI 项目。看起来每次当你要编写你提到的这样一个简单的场景时,你都必须重新发明轮子:(。当你使用 WPF 来做时,你甚至不需要考虑这一点,它太容易实现了,但是当你使用MAUI时,你应该打破头脑去做这些小事。
我也遇到了同样的问题,但没有找到简单的解决方案。但我想到了创建一个控件,其中包含一些布局,其中附加了 BindableLayout 的属性
TemplatedContentPresenter.xaml.cs:
public partial class TemplatedContentPresenter : ContentView
{
public TemplatedContentPresenter()
{
InitializeComponent();
}
public static readonly BindableProperty DataTemplateSelectorProperty = BindableProperty.Create(nameof(DataTemplateSelector), typeof(DataTemplateSelector), typeof(TemplatedContentPresenter), null, propertyChanged: DataTemplateSelectorChanged);
public static readonly BindableProperty DataTemplateProperty = BindableProperty.Create(nameof(DataTemplate), typeof(DataTemplate), typeof(TemplatedContentPresenter), null, propertyChanged: DataTemplateChanged);
public static readonly BindableProperty DataProperty = BindableProperty.Create(nameof(Data), typeof(object), typeof(TemplatedContentPresenter), null, propertyChanged: DataChanged);
public DataTemplateSelector DataTemplateSelector
{
get =>(DataTemplateSelector)GetValue(DataTemplateSelectorProperty);
set => SetValue(DataTemplateSelectorProperty, value);
}
public DataTemplate DataTemplate
{
get => (DataTemplate)GetValue(DataTemplateProperty);
set => SetValue(DataTemplateProperty, value);
}
public object Data
{
get => GetValue(DataProperty);
set => SetValue(DataProperty, value);
}
private static void DataTemplateSelectorChanged(BindableObject bindable, object oldValue, object newValue)
{
if(bindable is TemplatedContentPresenter contentPresenter && newValue is DataTemplateSelector dataTemplateSelector)
{
BindableLayout.SetItemTemplateSelector(contentPresenter.HostGrid, dataTemplateSelector);
}
}
private static void DataTemplateChanged(BindableObject bindable, object oldValue, object newValue)
{
if (bindable is TemplatedContentPresenter contentPresenter && newValue is DataTemplate dataTemplate)
{
BindableLayout.SetItemTemplate(contentPresenter.HostGrid, dataTemplate);
}
}
private static void DataChanged(BindableObject bindable, object oldValue, object newValue)
{
if (bindable is TemplatedContentPresenter contentPresenter)
{
BindableLayout.SetItemsSource(contentPresenter.HostGrid, new object[] { newValue });
}
}
}
Run Code Online (Sandbox Code Playgroud)
TemplatedContentPresenter.xaml:
<?xml version="1.0" encoding="utf-8" ?>
<ContentView xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="MyApp.TemplatedContentPresenter">
<Grid x:Name="HostGrid" x:FieldModifier="private" />
</ContentView>
Run Code Online (Sandbox Code Playgroud)
用法:
<Frame WidthRequest="500" HeightRequest="500">
<controls:TemplatedContentPresenter
Data="{Binding}"
DataTemplateSelector="{StaticResource CardTemplateSelector}"/>
</Frame>
Run Code Online (Sandbox Code Playgroud)
UPD: 当我写答案时,我想出了另一个带有简单转换器的解决方案: SingleObjectToArray.xaml
internal class SingleObjectToArray : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return new object[] { value };
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
Run Code Online (Sandbox Code Playgroud)
用法:
<Frame>
<Frame.Resources>
<converters:SingleObjectToArray x:Key="SingleObjectToArrayConverter"/>
</Frame.Resources>
<Grid BindableLayout.ItemsSource="{Binding Converter={StaticResource SingleObjectToArrayConverter}}"
BindableLayout.ItemTemplateSelector="{StaticResource CardTemplateSelector}" />
</Frame>
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4672 次 |
| 最近记录: |