首页 > 其他分享 >XAML中DataTemplate变量隐藏的解决方法

XAML中DataTemplate变量隐藏的解决方法

时间:2024-01-14 21:00:46浏览次数:27  
标签:... SamplePage XAML 隐藏 class DataTemplate public

title: XAML中DataTemplate变量隐藏的解决方法
date: 2023-11-13
categories: 编程
tags:
- C#
- .NET
- XAML

前言

微软的许多XAML框架,如WPF、UWP、WinUI3等,在DataTemplate下都会遇到变量隐藏(Variable shadowing)的问题。为了访问外部实例成员,经常需要写很多曲折的代码,但也没有办法。本文也无法解决这个问题,但记录了我知道的方法,以便在各种情况使用,争取将可读性的影响降到最低。

问题再现

按照需求创建了一个Page

public sealed partial class SamplePage : Page
{
    public string OuterMember { get; set; } = "OuterMember";

    public SamplePage()
    {
        ViewModels = new ViewModel[] { new("a"), new("b"), new("c"), };
        InitializeComponent();
    }

    public ViewModel[] ViewModels { get; }
}

public class ViewModel(string text)
{
    public string Text { get; set; } = text;
}
<Page
    x:Class="SampleApp.SamplePage"
    ...>
    <ItemsRepeater ItemsSource="{x:Bind ViewModels}">
        <ItemsRepeater.ItemTemplate>
            <DataTemplate x:DataType="local:ViewModel">
                <TextBlock Text="{x:Bind Text}" />
            </DataTemplate>
        </ItemsRepeater.ItemTemplate>
    </ItemsRepeater>
</Page>

大部分情况下,写到这种程度就能完成任务了。但有时候需要把外部的成员(如OuterMember)传给DataTemplate内的控件(如此处的TextBlock),那么如何实现呢?

首先可以发现,在DataTemplate内并非只能使用ViewModel类的成员,而还能访问以下这些东西:

  • static成员

  • StaticResource

  • 事件处理方法

据此我们就可以利用这些来实现跨域(scope)访问类实例成员。一共有三种思路:

解决方案

Static转实例

这是很常用的方法,就连官方库都可以看到这样的实现,例如Application.Current

那我们可以仿照这样写:

public sealed partial class SamplePage : Page
{
    public static SamplePage Current { get; private set; }

    public SamplePage()
    {
        Current = this;
        ...
    }
    ...
}

此时在XAML中就可以:

...
<DataTemplate x:DataType="local:ViewModel">
    <TextBlock Text="{x:Bind local:SamplePage.Current.OuterMember}" />
</DataTemplate>
...

这样写的优点是简洁明了,缺点是只能单例使用

StaticResource

这种方法也有人使用:

public class Box
{
    public object Content { get; set; }
}

public sealed partial class SamplePage : Page
{
    public SamplePage()
    {
        ...
        InitializeComponent();
        ((Box)Resources["Box"]).Content = OuterMember;
    }
    ...
}
...
<Page.Resources>
    <local:Box x:Key="Box" />
    <local:UnboxConverter x:Key="UnboxConverter" />
</Page.Resources>
<ItemsRepeater ItemsSource="{x:Bind ViewModels}">
    <ItemsRepeater.ItemTemplate>
        <DataTemplate x:DataType="local:ViewModel">
            <TextBlock Text="{Binding Converter={StaticResource UnboxConverter}, ConverterParameter={StaticResource Box}}" />
        </DataTemplate>
    </ItemsRepeater.ItemTemplate>
</ItemsRepeater>
...

Box是用来装箱的,防止使用值类型时复制赋值导致前后不是同一个对象。

这种方法优点是十分灵活,处理方法写在Converter里,传递参数写在Box里,可以随意扩展,几乎没有限制。

缺点也很明显,写了许多不明所以的代码,逻辑曲折难懂,Binding效率也较差。

事件处理

这种方法可以很方便地获取需要的参数,但可能需要多写一个子控件:

public sealed partial class SampleControl : UserControl
{
    public event Func<SamplePage>? ThisRequested;

    public string? GetOuterMember => ThisRequested?.Invoke().OuterMember;

    public SampleControl()
    {
        InitializeComponent();
    }
}
<UserControl
    x:Class="SampleApp.SampleControl"
    ...>
    <TextBlock Text="{x:Bind GetOuterMember}" />
</UserControl>

原页面只需:

public sealed partial class SamplePage : Page
{
    private SamplePage MyControlOnThisRequested() => this;
    ...
}
...
<DataTemplate x:DataType="local:ViewModel">
    <local:SampleControl ThisRequested="MyControlOnThisRequested"/>
</DataTemplate>
...

这种方法十分优雅,也很灵活,缺点是要单独写一个子控件。但如果由于DataTemplate内容太长,本来就打算分开写控件,那这个缺点就不存在了。

总之三个方法各有利弊,大家可以根据需要选择最合适的。

标签:...,SamplePage,XAML,隐藏,class,DataTemplate,public
From: https://www.cnblogs.com/pokersang/p/17964182

相关文章

  • 服务器IP如何隐藏
    说到IP地址,它足以作为服务器的定位标志,算是在互联网上的名片。因此,当一些黑客攻击服务器时,IP地址便会成为首要目标。为保护服务器避免受到潜在的攻击和侦察,隐藏服务器的真实IP地址是一项重要的措施。服务器IP隐藏的原理:服务器IP隐藏的基本原理是防止未经授权的用户通过直接......
  • Qt QTableView和QStandardItemModel模糊搜索出现的文本及隐藏顶层节点
    前言使用Qt进行开发时,树结构一般是使用QTreeWidget或使用QTreeView+QStandardItemModel结合。查找如果要进行查找树的所有项中,是否包含某文本,就需要遍历。QTreeWidget查找以下是使用QTreeWidget进行查找:首先初始化一些树结构QTreeWidget*pTW=newQTreeWidget(this);......
  • XAML x 名称空间的介绍
    WPF学习目录1.简介x名称空间映射http://schemas.microsoft.com/winfx/2006/xaml,包含解析XAML语言相关的类。XAML编译器将XAML编译成微软中间语言和C#编译器将C#编译也成微软中间语言,使用X名称空间可以将C#的编译结果和C#的编译结果合并。x名称空间是程序员能够和X......
  • 隐藏服务器IP的正确使用方式
    简介IP是英文InternetProtocol的缩写,意思是网络之间互连的协议,也就是为计算机网络相互连接进行通信而设计的协议。在因特网中,它是能使连接到网上的所有计算机网络实现相互通信的一套规则,规定了计算机在因特网上进行通信时应当遵守的规则。任何厂家生产的计算机系统,只要遵守IP协议......
  • Revit 中隐藏类别的两种方法
    方法1:RevitQ中隐藏类别有两种方法,模型类别,Reivt链接。以下需要用两种方法进行隐藏模型类别的是用SetCategoryHidden(Reit2016用SetVisibility)进行设置varelecategoryId=newElementId(-2000220);Transactiontr=newTransaction(doc);tr.start("链接模型");doc.ActiveV......
  • 元素显示与隐藏
    引入大家注意这个效果广告按钮,当我点击那个❌的时候,我们会发现广告自己会消失不见并且不会占有原来的位置。这里就要用到一个css的知识,隐藏displaydisplay属性用于设置一个元素应如何显示。none:元素不会被显示。block:元素显示为块级元素,像<p>、<div>这样的标签默认就是块级元......
  • 软件开发隐藏报价和虚假信息协议书,明确的如下2点关键原则
    软件开发外包已成为众多企业实现技术创新、降低成本的有效途径。然而,在这一领域中,不透明的定价策略和虚假信息问题屡见不鲜,给交易双方带来了不少困扰与风险。因此,为了保障企业的合法权益,签署包含隐藏报价和虚假信息赔偿条款的外包合同显得尤为重要。如下参考“东莞梦幻网络科技”......
  • 定制栏目 --- 关于el-table 的显示隐藏的列
      <el-button type="primary"plainicon="el-icon-s-operation"@click="columsVisible=true":loading="handleTotalChecked">定制栏目</el-button> 需要的页面引入组件:<divclass="tableList">    ......
  • fastadmin隐藏指定表格行的按钮
    一、隐藏修改,删除按钮(隐藏所有行)隐藏前修改代码varController={index:function(){//初始化表格参数配置Table.api.init({extend:{index_url:'department/index/index',ad......
  • 【内网渗透】隐藏cobaltstrike服务器—自定义证书+C2侧写
    简介自定义证书查看Cobaltstrike默认证书发现特征含有cobaltstrike关键字常用keytool命令查看证书文件:keytool-list-v-keystorexx.store修改证书密码:keytool-storepasswd-keystoretest.store修改alias别名:keytool-changealias-keystoretest.store-aliasso......