C# 如何创建可以在应用程序中任意位置设置/获取的应用程序范围变量?(WPF/MVVM)

C# 如何创建可以在应用程序中任意位置设置/获取的应用程序范围变量?(WPF/MVVM),c#,wpf,variables,mvvm,singleton,C#,Wpf,Variables,Mvvm,Singleton,我正在编写一个WPF应用程序,并试图学习有效的MVVM实践。我的界面(MainWindow.xaml内)中有MenuItem按钮,希望将其命令属性绑定到我创建的ICommand 当应用程序启动时,我希望将bool(可以从应用程序中的任何位置设置/获取)设置为最初设置为false。当“File>New”菜单项被激活时,我希望命令触发并检查其“CanExecute”方法中的应用程序范围变量,然后该方法应该启用或禁用菜单项 我的问题是,我无法确定存储/实例化/etc这个变量(或属性?)的最佳位置 我已

我正在编写一个WPF应用程序,并试图学习有效的MVVM实践。我的界面(MainWindow.xaml内)中有MenuItem按钮,希望将其命令属性绑定到我创建的ICommand

当应用程序启动时,我希望将bool(可以从应用程序中的任何位置设置/获取)设置为最初设置为false。当“File>New”菜单项被激活时,我希望命令触发并检查其“CanExecute”方法中的应用程序范围变量,然后该方法应该启用或禁用菜单项

我的问题是,我无法确定存储/实例化/etc这个变量(或属性?)的最佳位置

我已经尝试了多种不同的组合,包括用我的“Workspace”类(它包含布尔变量)实现一个单例模式设计,而且我现在正在修补静态类和变量

我的代码如下所示:

XAML:

<MenuItem Header="_File">
            <MenuItem Header="_New Project" Command="{Binding NewProjectCommand, Source={StaticResource project}}"/>
            <MenuItem Header="_Open Project"/>
</MenuItem>
public WorkspaceViewModel WorkspaceInfo { get; set; }

public partial class App : Application
{
    public App()
    {
        //Store variable here? How? And what is the best way to expose it to my Commands?
    }

}
class WorkspaceViewModel : Workspace
{

}
class NewProjectCommand : ICommand
{

    public NewProjectCommand(ProjectViewModel projectViewModel)
    {
    }

    public event EventHandler CanExecuteChanged;

    public bool CanExecute(object parameter)
    {
        //Do an evaluation here using the new bool in App.xaml.cs
        //return true/false, based on the evaluation

    }

    public void Execute(object parameter)
    {
        //Perform steps here to switch the bool in App.xaml.cs, and perform other command functionality
    }
}
class Workspace : INotifyPropertyChanged
{
    private bool _isProjectOpen;

    public bool IsProjectOpen
    {
        get { return _isProjectOpen; }
        set
        {
            _isProjectOpen = value;
            OnPropertyChanged();
        }
    }


    #region INotifyPropertyChanged members

    public event PropertyChangedEventHandler PropertyChanged;

    private void OnPropertyChanged([CallerMemberName] string propertyName = "")
    {
        var handler = PropertyChanged;

        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }
    #endregion
}
WorkspaceViewModel.cs:

<MenuItem Header="_File">
            <MenuItem Header="_New Project" Command="{Binding NewProjectCommand, Source={StaticResource project}}"/>
            <MenuItem Header="_Open Project"/>
</MenuItem>
public WorkspaceViewModel WorkspaceInfo { get; set; }

public partial class App : Application
{
    public App()
    {
        //Store variable here? How? And what is the best way to expose it to my Commands?
    }

}
class WorkspaceViewModel : Workspace
{

}
class NewProjectCommand : ICommand
{

    public NewProjectCommand(ProjectViewModel projectViewModel)
    {
    }

    public event EventHandler CanExecuteChanged;

    public bool CanExecute(object parameter)
    {
        //Do an evaluation here using the new bool in App.xaml.cs
        //return true/false, based on the evaluation

    }

    public void Execute(object parameter)
    {
        //Perform steps here to switch the bool in App.xaml.cs, and perform other command functionality
    }
}
class Workspace : INotifyPropertyChanged
{
    private bool _isProjectOpen;

    public bool IsProjectOpen
    {
        get { return _isProjectOpen; }
        set
        {
            _isProjectOpen = value;
            OnPropertyChanged();
        }
    }


    #region INotifyPropertyChanged members

    public event PropertyChangedEventHandler PropertyChanged;

    private void OnPropertyChanged([CallerMemberName] string propertyName = "")
    {
        var handler = PropertyChanged;

        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }
    #endregion
}
NewProjectCommand.cs:

<MenuItem Header="_File">
            <MenuItem Header="_New Project" Command="{Binding NewProjectCommand, Source={StaticResource project}}"/>
            <MenuItem Header="_Open Project"/>
</MenuItem>
public WorkspaceViewModel WorkspaceInfo { get; set; }

public partial class App : Application
{
    public App()
    {
        //Store variable here? How? And what is the best way to expose it to my Commands?
    }

}
class WorkspaceViewModel : Workspace
{

}
class NewProjectCommand : ICommand
{

    public NewProjectCommand(ProjectViewModel projectViewModel)
    {
    }

    public event EventHandler CanExecuteChanged;

    public bool CanExecute(object parameter)
    {
        //Do an evaluation here using the new bool in App.xaml.cs
        //return true/false, based on the evaluation

    }

    public void Execute(object parameter)
    {
        //Perform steps here to switch the bool in App.xaml.cs, and perform other command functionality
    }
}
class Workspace : INotifyPropertyChanged
{
    private bool _isProjectOpen;

    public bool IsProjectOpen
    {
        get { return _isProjectOpen; }
        set
        {
            _isProjectOpen = value;
            OnPropertyChanged();
        }
    }


    #region INotifyPropertyChanged members

    public event PropertyChangedEventHandler PropertyChanged;

    private void OnPropertyChanged([CallerMemberName] string propertyName = "")
    {
        var handler = PropertyChanged;

        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }
    #endregion
}
Workspace.cs:

<MenuItem Header="_File">
            <MenuItem Header="_New Project" Command="{Binding NewProjectCommand, Source={StaticResource project}}"/>
            <MenuItem Header="_Open Project"/>
</MenuItem>
public WorkspaceViewModel WorkspaceInfo { get; set; }

public partial class App : Application
{
    public App()
    {
        //Store variable here? How? And what is the best way to expose it to my Commands?
    }

}
class WorkspaceViewModel : Workspace
{

}
class NewProjectCommand : ICommand
{

    public NewProjectCommand(ProjectViewModel projectViewModel)
    {
    }

    public event EventHandler CanExecuteChanged;

    public bool CanExecute(object parameter)
    {
        //Do an evaluation here using the new bool in App.xaml.cs
        //return true/false, based on the evaluation

    }

    public void Execute(object parameter)
    {
        //Perform steps here to switch the bool in App.xaml.cs, and perform other command functionality
    }
}
class Workspace : INotifyPropertyChanged
{
    private bool _isProjectOpen;

    public bool IsProjectOpen
    {
        get { return _isProjectOpen; }
        set
        {
            _isProjectOpen = value;
            OnPropertyChanged();
        }
    }


    #region INotifyPropertyChanged members

    public event PropertyChangedEventHandler PropertyChanged;

    private void OnPropertyChanged([CallerMemberName] string propertyName = "")
    {
        var handler = PropertyChanged;

        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }
    #endregion
}
我基本上希望在应用程序的最高级别存储一个真/假值,这样我就可以在“CanExecute”中获取变量,并在所有ICommand的“Execute”方法中设置变量,这样我的所有菜单项都将在适当的时间启用和禁用

我意识到这是一个相当冗长的问题,但任何帮助都是非常感谢的,如果我需要发布任何额外的信息,我将很高兴这样做


提前谢谢大家

将值存储在静态
应用程序的
属性
字典中。当前
实例:

Application.Current.Properties["NameOfProperty"] = false;
var myProperty = (bool)Application.Current.Properties["NameOfProperty"];

将值存储在静态
应用程序的
属性
字典中。当前
实例:

Application.Current.Properties["NameOfProperty"] = false;
var myProperty = (bool)Application.Current.Properties["NameOfProperty"];
两种方式
1.]将它们另存为项目设置
右键单击项目,然后单击属性并转到设置
在此处创建您的设置。
您可以访问或操纵它们 在代码中以编程方式

Properties.Settings.Default.SavedInputString
2.]将它们存储在自定义xml文件中
Xml文件易于创建、读取和更新,是一种快速加载的方式 运行时设置两种方式
1.]将它们另存为项目设置
右键单击项目,然后单击属性并转到设置
在此处创建您的设置。
您可以访问或操纵它们 在代码中以编程方式

Properties.Settings.Default.SavedInputString
2.]将它们存储在自定义xml文件中
Xml文件易于创建、读取和更新,是一种快速加载的方式 在运行时设置“应用程序范围变量”可以在应用程序类中声明为属性:

public partial class App : Application
{
    public bool YourProperty { get; set; } // is false by default
}
现在,属性“可以在应用程序中的任何位置设置/获取”由

“应用程序范围变量”可以声明为应用程序类中的属性:

public partial class App : Application
{
    public bool YourProperty { get; set; } // is false by default
}
现在,属性“可以在应用程序中的任何位置设置/获取”由


单身汉怎么了?正如不同的答案所描述的,有很多方法可以做到这一点。如果您正在学习MVVM的最佳实践,我建议将此变量放入用于存储应用程序状态的模型/服务中,并将其接口注入所有必须了解应用程序状态的ViewModels中。这样就不会破坏ViewModels的可测试性。在我考虑潜在选项的整个过程中,我真的希望有一个简单的解决方案,我可以使用。我有点倾向于一个易于访问的属性,而不是一个单一的属性,尽管我希望最终能够学会如何使用它。谢谢单身汉怎么了?正如不同的答案所描述的,有很多方法可以做到这一点。如果您正在学习MVVM的最佳实践,我建议将此变量放入用于存储应用程序状态的模型/服务中,并将其接口注入所有必须了解应用程序状态的ViewModels中。这样就不会破坏ViewModels的可测试性。在我考虑潜在选项的整个过程中,我真的希望有一个简单的解决方案,我可以使用。我有点倾向于一个易于访问的属性,而不是一个单一的属性,尽管我希望最终能够学会如何使用它。谢谢OP显然不想存储和重新加载属性值。您建议的两个选项对我的应用程序中的其他机制都非常有用,因此我肯定要在设置中存储用户定义的“首选项”。实际上,我正在使用该应用程序将用户输入的数据写入一个XML文件,因此我将很快着手这一部分。我在考虑我的不同选项,这将是我的下一个障碍之一。hahaOP显然不想存储和重新加载属性值。您建议的两个选项对我的应用程序中的其他机制都非常有用,因此我肯定要在设置中存储用户定义的“首选项”。实际上,我正在使用该应用程序将用户输入的数据写入一个XML文件,因此我将很快着手这一部分。我在考虑我的不同选择,这将是我的下一个障碍之一,哈哈蒂是完美的——这正是我所需要的。我认为我的问题是一个事实,即我没有在第一时间正确调用属性来设置它。除此之外,我的MenuItem.IsEnabled没有正确更新,因为我的命令的“CanExecuteChanged”方法中没有任何内容!这是完美的-正是我需要的。我认为我的问题是一个事实,即我没有在第一时间正确调用属性来设置它。除此之外,我的MenuItem.IsEnabled没有正确更新,因为我的“CanExecuteChan”中没有任何内容