C# 在WPF/MVVM应用程序中设置编辑状态

C# 在WPF/MVVM应用程序中设置编辑状态,c#,wpf,mvvm,C#,Wpf,Mvvm,在WPF应用程序中使用MVVM模式,我希望处理记录的“编辑状态”。 每次用户开始编辑记录时,该窗口都应切换到“编辑”模式,在代码中很容易用名为IsEditing的布尔属性表示。 这允许激活/停用UI按钮等 我知道这样的属性应该包含在ViewModel中。 但是,如何确保一旦用户开始编辑其中一个字段,IsEditing就设置为true? 我发现的唯一方法是将IsEditing显式分配到模型字段的包装器中。 有没有更好、更聪明的方法来做到这一点,也许是以集中的方式?我在我的方法中看到的缺点是,对于一

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

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

但是,我的模型实体框架核心应该是不相关的:

public class City
{
    public string Id { get; set; }
    public string Name { get; set; }
}
关联的ViewModel I仅包含相关代码:

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;
            }
        }
    }

}

我理解你的问题,并且已经有了同样的问题。我的解决方案是基于触发器触发commmands for 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}" />
不要忘记设置模式:双向

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

我做了一个小项目来测试它,自由地看了看


无论如何,你的虚拟机是没有意义的。避免堆栈溢出的唯一方法是检查IsEditing是否不同,因为您在setter中用true覆盖了用户的值。您完全正确,直接在stackoverflow上编辑代码是一个错误。IsEditing由任何其他属性设置,但显然不是由其自身设置的。我现在已经改正了。