WPF 自定义控件将文本框文本重置为默认值
Posted
技术标签:
【中文标题】WPF 自定义控件将文本框文本重置为默认值【英文标题】:WPF Custom control reset textbox text to a default value 【发布时间】:2021-11-08 17:36:50 【问题描述】:我需要一个带有按钮的文本框,它必须显示默认值,但仍应允许用户输入我需要存储在 ViewModel 属性中的文本。 该按钮应将值重置为默认值。
我在这个实现中遇到了一些问题:
当用户在文本框中键入时,我希望我的 viewModel 中的绑定属性会相应更新,但似乎不再有绑定。 (绑定设置两种方式) (绑定和 DataContext 是正确的,因为加载时显示的是从 ViewModel 设置的值)
一旦我在框中键入并点击恢复按钮,文本将按预期分配给属性,但文本框仍由用户显示相同的值类型。
每次我在选项卡上移动或单击另一个控件时,负责将文本还原回来的按钮需要单击两次(看起来像焦点问题),因为一旦焦点位于文本框中,一切正常。
如果我定义了控制模板,我已经创建了一个 Generic.xaml。
<Style x:Key="x:Type local:RememberValue" TargetType="x:Type local:RememberValue">
<Setter Property="Background" Value="StaticResource RemeberValue_Background" />
<Setter Property="BorderBrush" Value="StaticResource RemeberValue_Border" />
<Setter Property="Foreground" Value="StaticResource RemeberValue_Foreground" />
<Setter Property="BorderThickness" Value="1" />
<Setter Property="Focusable" Value="True" />
<Setter Property="SnapsToDevicePixels" Value="True" />
<Setter Property="FocusVisualStyle" Value="x:Null"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="x:Type local:RememberValue">
<Grid x:Name="LayoutGrid">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<baseControlUi:IconButton
Grid.Column="0"
Height="22"
Grid.ZIndex="1"
Margin="0"
EllipseDiameter="19"
Focusable="True"
Visibility="Binding ElementName=RememberValueControl, Path=IsDifferentValue, Converter=StaticResource BooleanToVisibilityConverter"
ButtonCommand="TemplateBinding RevertCommand"
ButtonIcon="StaticResource RevertIcon" />
<TextBox
Grid.ZIndex="0"
Foreground="StaticResource RemeberValue_Foreground"
Text="TemplateBinding DisplayText"
HorizontalAlignment="Stretch"
VerticalAlignment="Center" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
这是视图中的用法。
<StackPanel Width="400">
<remebervalue:RememberValue
DisplayText="Binding DisplayText, UpdateSourceTrigger=PropertyChanged"
DefaultValue="Binding DefaultText, UpdateSourceTrigger=PropertyChanged"
HorizontalAlignment="Left" Width="400" />
</StackPanel>
RemeberValue.cs 后面的代码为 DisplayText 和 DefaultText 注册了 DP
public static readonly DependencyProperty DisplayTextProperty =
DependencyProperty.Register(nameof(DisplayText), typeof(string), typeof(RememberValue), new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnDisplayText_Changed));
public RememberValue()
RevertCommand = new SimpleCommand(Revert);
private void Revert()
DisplayText = DefaultValue;
public string DisplayText
get => (string)GetValue(DisplayTextProperty);
set => SetValue(DisplayTextProperty, value);
private static void OnDisplayText_Changed(DependencyObject d, DependencyPropertyChangedEventArgs e)
RememberValue RememberValue = d as RememberValue;
【问题讨论】:
感谢重播我已编辑问题。 ontext changed 方法目前是“空的”。 我认为DisplayText
属性和OnDisplayText_Changed()
方法没有问题。如果你没有在里面放任何东西,你可以删除这个方法,创建FrameworkPropertyMetadata
不是强制性的。不过,您可能想添加OnPropertyChanged(nameof(IsDifferentValue))
。您是否有一个 ViewModel,其中有 DisplayText
和 DefaultText
属性?名称 DefaultText
和 DefaultValue
之间的差异是故意的吗?在调试中运行项目时,输出窗口中是否没有错误?
我知道现在不使用了,我会删除它。你是对的,是复制和粘贴错误。我将其更改为 DisplayText = DefaultText;目前剩下的问题只是在需要单击两次才能触发命令的控件上。而且我仍然认为问题出在焦点上,这可能是我使用 z 索引的事实吗?
我很少用z-index,所以不知道。您可以尝试删除它,并在 XAML 中将 IconButton
移动到 TextBox
之后吗?如果这不能解决您的问题,那么在网格中添加一列并将按钮移动到该列,或者将 Grid
更改为 StackPanel
怎么样?
如果在 agrid 中有或没有 z 索引的面板中没有变化,我认为查看焦点是我设法提高可用性的正确方法。设置这个。 部分回答
第一点:我相信你写错了“Binding is set two way”,因为你使用的是TemplateBinding
,即always one-way。您应该将其替换为
Binding DisplayText, RelativeSource=RelativeSource TemplatedParent, Mode=TwoWay
第二点:由上述固定
第三点:不同的问题,需要在不同的问题中解决。
【讨论】:
刚刚测试了您的示例并且正在运行,现在绑定是 2 方式。 (真实)。以上是关于WPF 自定义控件将文本框文本重置为默认值的主要内容,如果未能解决你的问题,请参考以下文章
将 WPFToolkit DatePickerTextBox 控件重写为自定义组合框控件
WPF自定义控件与样式-TextBox & RichTextBox & PasswordBox样式水印Label标签功能扩展