C# 如何创建可以在应用程序中任意位置设置/获取的应用程序范围变量?(WPF/MVVM)
我正在编写一个WPF应用程序,并试图学习有效的MVVM实践。我的界面(MainWindow.xaml内)中有MenuItem按钮,希望将其命令属性绑定到我创建的ICommand 当应用程序启动时,我希望将bool(可以从应用程序中的任何位置设置/获取)设置为最初设置为false。当“File>New”菜单项被激活时,我希望命令触发并检查其“CanExecute”方法中的应用程序范围变量,然后该方法应该启用或禁用菜单项 我的问题是,我无法确定存储/实例化/etc这个变量(或属性?)的最佳位置 我已经尝试了多种不同的组合,包括用我的“Workspace”类(它包含布尔变量)实现一个单例模式设计,而且我现在正在修补静态类和变量 我的代码如下所示: XAML: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这个变量(或属性?)的最佳位置 我已
<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”中没有任何内容