简体   繁体   English

在 WPF/MVVM 应用程序中设置编辑 state

[英]set Editing state in a WPF/MVVM application

Using the MVVM pattern in a WPF application, I want to handle the 'Editing State' of a record .在 WPF 应用程序中使用 MVVM 模式,我想处理记录的“编辑状态”
Every time the user starts editing a record, that window should switch to the 'editing' mode, easily represented in code by a boolean property named IsEditing .每次用户开始编辑记录时,window 都应该切换到“编辑”模式,这很容易在代码中由名为 IsEditing 的IsEditing属性表示。
This allows for activating/deactivating UI buttons etc. etc.这允许激活/停用 UI 按钮等。

I've understood that such a property should go into the ViewModel.我知道这样的属性应该 go 到 ViewModel 中。
But how to make sure that as soon as the user starts editing one of the fields, IsEditing is set to true?但是如何确保用户开始编辑其中一个字段时, IsEditing设置为 true?
The only way I've found is to explicitly assign IsEditing into the wrappers of the model's fields.我发现的唯一方法是将IsEditing显式分配到模型字段的包装器中。 Is there a better, smarter way to do this, maybe in a centralized way?有没有更好、更聪明的方法来做到这一点,也许是集中式的? The cons that I see in my approach is the verbosity and the possiblity of forgetting to do so for a field.我在我的方法中看到的缺点是冗长和忘记为某个领域这样做的可能性。
Maybe there's an entirely different approach that handles such an issue right from the beginning?也许有一种完全不同的方法可以从一开始就处理这样的问题?

My model (Entity Framework Core, though should be irrelevant):我的 model (实体框架核心,虽然应该无关紧要):

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

The associated ViewModel (I included only the relevant code):关联的 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;
            }
        }
    }

}

I understood your problem and already had the same problem.我了解您的问题,并且已经遇到了同样的问题。 My solution was based in Triggers firing commmands for GotFocus and LostFocus updating the boolean, I know that is not the best option but was the only one I had.我的解决方案基于触发 GotFocus 和 LostFocus 更新 boolean 的命令,我知道这不是最好的选择,但它是我唯一的选择。

I'll prepare one snipped and update my reply.我会准备一份剪报并更新我的回复。

Edit: I found a better way to do it.编辑:我找到了一种更好的方法。

Creating a behavior and attaching it to your textbox, is a cleaner solution.创建一个行为并将其附加到您的文本框,是一种更清洁的解决方案。 It wont let your code dirty as my first suggestion.作为我的第一个建议,它不会让你的代码变脏。 :) :)

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
}

and in your text box:并在您的文本框中:

 <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}" />

Do not forget to put the Mode:TwoWay不要忘记把模式:TwoWay

The 'IsEditingEnabled' has to exists due the necessity of get the textbox reference to hook the events, so when the window is loading the 'OnIsEditingEnabledChanged' will be fired giving you the right control to "monitor". 'IsEditingEnabled' 必须存在,因为需要获取文本框引用以挂钩事件,因此当 window 加载时,'OnIsEditingEnabledChanged' 将被触发,让您可以正确控制“监控”。 Of course, if you want to implement a control to stop to monitor the editing state or change the event you'll change there.当然,如果你想实现一个控件来停止监听编辑state或者改变事件你会在那里改变。

I did a small project to test it, fell free to take a look.我做了一个小项目来测试它,随意看看。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM