【问题标题】:set Editing state in a WPF/MVVM application在 WPF/MVVM 应用程序中设置编辑状态
【发布时间】:2019-11-15 16:46:21
【问题描述】:

在 WPF 应用程序中使用 MVVM 模式,我想处理记录的“编辑状态”
每次用户开始编辑记录时,该窗口都应该切换到“编辑”模式,这很容易在代码中由名为 IsEditing 的布尔属性表示。
这允许激活/停用 UI 按钮等。

我知道这样的属性应该进入 ViewModel。
但是如何确保用户开始编辑其中一个字段时,IsEditing 设置为 true?
我发现的唯一方法是将IsEditing 显式分配到模型字段的包装器中。 有没有更好、更聪明的方法来做到这一点,也许是集中式的?我在我的方法中看到的缺点是冗长并且可能忘记为某个字段这样做。
也许有一种完全不同的方法可以从一开始就处理这样的问题?

我的模型(Entity Framework Core,虽然应该无关紧要):

public class City
{
    public string Id { get; set; }
    public string Name { get; set; }
}

关联的 ViewModel(我只包含了相关代码):

public class CityVM : INotifyPropertyChanged
{

    private bool _isEditing;
    public bool IsEditing
    {
        get { return _isEditing; }
        set
        {
            if (value!=_isEditing)
            {
                _isEditing = value;
                NotifyPropertyChanged(); 

            }
        }
    }

    public string Name
    {
        get { return _model.Name; }
        set
        {

            if (value!=_model.Name) 
            {
                _model.Name = value;
                NotifyPropertyChanged();
                IsEditing = true;
            }
        }
    }

}

【问题讨论】:

  • 就其价值而言,您的 VM 没有任何意义。唯一能让你免于堆栈溢出的方法是检查 IsEditing 是否不同,因为你在 setter 中用 true 覆盖了来自用户的值。
  • 你说得对,直接在stackoverflow上编辑代码是个错误。 IsEditing 由任何其他属性设置,但显然不是由其自身设置。我现在已经更正了。

标签: c# wpf mvvm


【解决方案1】:

我了解您的问题,并且已经遇到了同样的问题。我的解决方案是基于触发 GotFocus 和 LostFocus 更新布尔值的触发命令,我知道这不是最好的选择,但却是我唯一的选择。

我会准备一份剪报并更新我的回复。

编辑:我找到了更好的方法。

创建一个行为并将其附加到您的文本框,是一种更简洁的解决方案。作为我的第一个建议,它不会让你的代码变脏。 :)

public static class EditingStateBehavior
{
    #region IsEditing

    public static bool GetIsEditing(DependencyObject obj) => (bool)obj.GetValue(IsEditingProperty);

    public static void SetIsEditing(DependencyObject obj, bool value) => obj.SetValue(IsEditingProperty, value);

    public static readonly DependencyProperty IsEditingProperty =
       DependencyProperty.Register(
       "IsEditing",
       typeof(bool),
       typeof(EditingStateBehavior));

    #endregion IsEditing

    #region Enabling

    public static bool GetIsEditingEnabled(DependencyObject obj) => (bool)obj.GetValue(IsEditingEnabledProperty);

    public static void SetIsEditingEnabled(DependencyObject obj, bool value) => obj.SetValue(IsEditingEnabledProperty, value);

    public static readonly DependencyProperty IsEditingEnabledProperty =
        DependencyProperty.Register(
        "IsEditingEnabled",
        typeof(bool),
        typeof(TextBox),
        new PropertyMetadata(OnIsEditingEnabledChanged));

    private static void OnIsEditingEnabledChanged(object sender, DependencyPropertyChangedEventArgs e)
    {
        TextBox textBox = sender as TextBox;
        if (textBox is null) return;

        textBox.GotFocus += (x, p) => UpdateStatus(x as FrameworkElement, true);
        textBox.LostFocus += (x, p) => UpdateStatus(x as FrameworkElement, false);

        //Also, you cam implement something to handle if you don't want to receive notifications anymore....
    }

    private static void UpdateStatus(FrameworkElement frameworkElement, bool value) => frameworkElement.SetValue(IsEditingProperty, value);

    #endregion Enabling
}

在你的文本框中:

 <TextBox
        Grid.Row="1"
        Margin="3" Grid.ColumnSpan="1"
        VerticalContentAlignment="Center"
        local:EditingStateBehavior.IsEditing="{Binding IsEditing, Mode=TwoWay}"
        local:EditingStateBehavior.IsEditingEnabled="True"
        Text="{Binding SomeText}" />

别忘了设置 Mode:TwoWay

'IsEditingEnabled' 必须存在,因为需要获取文本框引用以挂钩事件,因此当窗口加载时,'OnIsEditingEnabledChanged' 将被触发,从而为您提供“监控”的正确控制权。当然,如果你想实现一个控件来停止监视编辑状态或改变事件你会在那里改变。

我做了一个小项目来测试它,有空看看。

https://github.com/mateusavelar/EditingStatePoc-WPF

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-10-21
    • 2012-04-18
    • 2012-08-05
    • 2013-03-27
    • 2022-01-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多