wpf - 控件模板中的 UWP 双向绑定
问题描述
我有一个带有 Text 属性的自定义控件,它应该双向绑定到数据上下文的属性。
绑定仅在开始时发生(我猜是一次),但不响应任何文本更改。
我的自定义控件:
public sealed class MyTextControl : Control
{
public static readonly DependencyProperty TextProperty = DependencyProperty.Register(
"Text", typeof(string), typeof(MyTextControl), new PropertyMetadata(default(string)));
public string Text
{
get => (string)GetValue(TextProperty);
set => SetValue(TextProperty, value);
}
public MyTextControl()
{
DefaultStyleKey = typeof(MyTextControl);
}
}
控制模板:
<Style TargetType="local:MyTextControl">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:MyTextControl">
<Border
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<TextBox
BorderBrush="Black"
BorderThickness="1"
Text="{Binding Text, RelativeSource={RelativeSource TemplatedParent}}" />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
我打电话给控制:
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
<myTextControl:MyTextControl
Width="500"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Text="{x:Bind Greeting, Mode=TwoWay}" />
<Button
Margin="50"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Content="Submit" />
</StackPanel>
Greeting 是 DP 在代码后面设置为 Hello World!
我希望在“问候语”或“文本更改文本”中达到一个断点,但我没有。
似乎双向绑定效果不佳。与 WPF 有什么不同?我怎样才能使它工作?
解决方案
快速回答
其次,从 Windows 10 版本 1809 开始,您可以在{x:Bind}
{TemplateBinding}
ControlTemplate
.
因此,您可以{x:Bind}
在 a 内部使用ControlTemplate
而不是{TemplateBinding}
并具有双向绑定功能( mode=TwoWay
)。
额外帮助
话虽如此,{x:Bind}
在 a 内部使用ControlTemplate
并不像替换{TemplateBinding}
with的实例那么简单{x:Bind}
。它涉及一些其他的变化。考虑到 Visual Studio 会自动 (1) 创建一个名为的类文件MyControl.cs
并 (2) 使用 inside 分配控件的样式ControlTemplate
(SomeProject\Themes\Generic.xaml
如果文件夹和资源文件不存在,则会创建它们),请按照这些说明进行操作您的控件使用 {x:Bind}:
在该文件夹
Themes\
中,创建一个名为的新类文件Generic.xaml.cs
并声明一个公共密封部分类,该类Generic
使用一个公共构造函数命名,该构造函数只调用InitializeComponent
:// Themes\Generic.xaml.cs namespace SomeSolution.SomeProject.Themes { public sealed partial class Generic { public Generic() => InitializeComponent(); } }
(见注 A。)
将以下内容作为属性添加到 的根标记
Generic.xaml
:<!-- Themes\Generic.xaml --> <ResourceDictionary x:Class="SomeProject.Themes.Generic" ...> ... </ResourceDictionary>
(见注 B。)
Generic
在 ( ) 中实例化包含控件样式的 ready-for-xBind 类型 (Application.Resources
).MergedDictionaries
:<!-- App.xaml --> <Application ...> <Application.Resource> <Generic xmlns="using:Whatever.Namespace" /> </Application.Resources> ... </Application>
(见注释 C、D 和 E。)
笔记
A.{x:Bind}
标记扩展在编译时生成源代码,因此需要对生成的代码进行初始化]。
B.连接标记和代码隐藏之间的x:Class
部分类]。
C.通过实例化它的类型(这样InitializeComponent
被调用)而不是引用它的文件名来重用带有代码隐藏的资源字典。
D.Application.Resources
可以到处重复使用。如果不打算这样做,则可以在 , 等中实例化具有样式的SomePage.Resources
类SomeFrameworkElement.Resources
。
E.Themes\Generic.xaml
不需要Application.Resources
为了让它们在任何地方都可用而“合并”其中的资源。它们按约定提供。但是,由于此资源字典确实需要显式实例化,因此无需命名文件Generic.xaml
和Generic.xaml.cs
(within Themes/
)。文件(和类)可以命名不同,命名空间和位置也可以不同。只要它们被相应地实例化,控件就会起作用。
推荐阅读
- javascript - RequireJS 的配置以咨询 node_modules?
- ios - 难以处理集合视图单元的可重用性。
- kubernetes - Pod 中的 2 个容器是否可以共享相同的环境变量?
- python - 比较 Pandas Dataframe 的列名
- swift - 将字符串从自定义分段控件设置为 UITextField 导致崩溃
- mysql - MySQL多次选择条件列
- python - 如何将整数加入列表中,使得: ['a',1,2] 变为 ['a',12]
- regex - nginx 位置包含字符串 + 以结尾
- node.js - 在nodejs中连接到heroku postgres db时出错
- reactjs - 1.8mb 对 Webpack 是好还是坏?