【发布时间】: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 索引的面板中没有变化,我认为查看焦点是我设法提高可用性的正确方法。设置这个。
这让我可以立即单击按钮,但是一旦我切换选项卡控件,就会触发丢失焦点事件,我仍然需要再次单击按钮两次。
标签: c# wpf mvvm user-controls