我想知道在WPF中每个应用程序具有给定Window的单个实例的最佳方法(读起来最优雅)。
我是.NET和WPF的新手,我的想法看起来很la脚。
private static readonly Object MUTEX = new Object();
private static AboutWindow INSTANCE;
public static AboutWindow GetOrCreate() {
lock (MUTEX) {
if (INSTANCE == null) {
INSTANCE = new AboutWindow();
}
INSTANCE.Show();
return INSTANCE;
}
}
private AboutWindow() {
InitializeComponent();
}
private void AboutWindow_Closed(object sender, EventArgs e) {
// the Closed events are handy for me to update values across
// different windows.
lock (MUTEX) {
INSTANCE = null;
}
}
事情是...这看起来简直是胡扯。必须有某种方法以更优雅的方式实现相同的目标,对吗?
PS:我经常使用
Closed
事件来更改其他打开的窗口中的值。例如,我具有带有“帐户”按钮的 SettingsWindow 。当我按下该按钮时,弹出 AccountWindow 。当我关闭 AcountWindow 时,我希望 SettingsWindow 中的某些内容发生更改(标签)。因此,不断创建窗口。此外,由于窗口框架上的X按钮,关闭始终是您必须处理的事情...
最佳答案
如果您确实需要强制执行窗口的单个实例,那么使用工厂创建方法的静态实例(某种程度上具有您所拥有的风格)无疑是一个可行的选择,就像在处理数据库时使用单个DataContext实例一样。
您也可以编写自己的WindowManager类,尽管这看起来有些过分,并且本质上是同一件事(除了Factory方法将在单个类中)。
但是,重新阅读您的文章后,我想知道这是否是因为缺少树木而缺少森林的情况。提到您的SettingsWindow(又称为AccountWindow)时,我认为您应该只使用ShowDialog()。这将以模态方式打开一个窗口,这意味着不能与调用窗口(或应用程序中的任何其他窗口)进行交互。您只需在该对话框中设置一个属性,在按下“确定”按钮时将DialogResult设置为true,然后在父窗口中读取该属性。
基本上,您只需要像这样使用ShowDialog。在绑定(bind)与硬编码控件之间,我遗漏了很多实现细节。这些细节并不像仅查看ShowDialog的工作原理那么重要。
为简单起见,假设您有一个名为MyAppOptions的类,它很好地反射(reflect)了应用程序的选项。为了简单起见,我将省略大多数实现细节,但可能会实现INotifyPropertyChanged,具有方法,字段和属性等。
public class MyAppOptions
{
public MyAppOptions()
{
}
public Boolean MyBooleanOption
{
get;
set;
}
public String MyStringOption
{
get;
set;
}
}
然后,让它变得简单,并假设您要在按下某个窗口上的按钮时显示“选项”对话框。此外,我将假定您的选项中设置了一些变量,这些变量是在启动时加载的。
void btnOptions_Click(object sender, RoutedEventArgs e)
{
MyAppOptions options = new MyAppOptions();
options.MyBooleanOption = mSomeBoolean;
options.MyStringOption = mSomeString;
OptionsDialog optionsDialog = new optionsDialog(options);
if (optionsDialog.ShowDialog() == true)
{
// Assume this function saves the options to storage
// and updates the application (binding) appropriately
SetAndSaveOptions(optionsDialog.AppOptions);
}
}
现在,假设OptionsDialog是您在项目中创建的窗口,并且上面具有与MyBooleanOption相关的CheckBox和MyStringOption的TextBox。它还具有“确定”按钮和“取消”按钮。后面的代码可能会使用Binding,但是现在我们将对值进行硬编码。
public class OptionsDialog : Window
{
public OptionsDialog(MyAppOptions options)
{
chkBooleanOption.IsChecked = options.SomeBooleanOption;
txtStringOption.Text = options.SomeStringOption;
btnOK.Click += new RoutedEventHandler(btnOK_Click);
btnCancel.Click += new RoutedEventHandler(btnCancel_Click);
}
public MyAppOptions AppOptions
{
get;
set;
}
void btnOK_Click(object sender, RoutedEventArgs e)
{
this.AppOptions.SomeBooleanOption = (Boolean) chkBooleanOption.IsChecked;
this.AppOptions.SomeStringOption = txtStringOption.Text;
// this is the key step - it will close the dialog and return
// true to ShowDialog
this.DialogResult = true;
}
void btnClose_Click(object sender, RoutedEventArgs e)
{
// this will close the dialog and return false to ShowDialog
// Note that pressing the X button will also return false to ShowDialog
this.DialogResult = false;
}
}
就实现细节而言,这是一个非常基本的示例。在线搜索ShowDialog以获取更多详细信息。要记住的重要关键是:
表示这是您唯一的窗口
可以交互的应用程序
和。
将关闭对话框,可以是
从主叫方检查。
同时关闭对话框
您可以跳过更新中的值
调用窗口。
在窗口上自动设置
DialogResult为假
关于C#WPF如何强制执行Windows的单个实例,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/3983124/