使用 MVVM (C# WPF),您如何在应用程序初始化时将设置显示到各自的控件中?
With MVVM (C# WPF) how do you display settings into their respective controls upon app initialization?
我有 3 个组合框绑定到名为 ARDAR
的对象,其属性为 ARFlag
、DARFlag
和 ConfirmedFlag
。当从 ComboBox
中选择一个标志时,其 ID 将保存在设置中 (Properties.Settings.Default.ARFlag = aRFlag.flag1;
)。
应用程序启动时,会通过 XAML 创建 ARDAR
对象的实例。对象的构造函数检查非零值的设置,如果有值 (if (Properties.Settings.Default.ARFlag != 0) ARFlag = sa.flags.Where(f => f.flag1 == Properties.Settings.Default.ARFlag).FirstOrDefault();
)
则更新 属性
这会触发 OnPropertyChanged
方法,我认为该方法会更新组合框,然后显示已保存设置的选择。但是,在初始化应用程序时,组合框留空。我确保 ARDAR
的属性实际上已更改为其各自的设置,并且 OnPropertyChanged
实际上正在触发。那么,我错过了什么?如何让组合框显示它们保存的设置?
这是我的 XAML & C# 代码:
public class ARDAR : INotifyPropertyChanged
{
public ARDAR()
{
var sa = new SALinqDataContext();
if (Properties.Settings.Default.ARFlag != 0) ARFlag = sa.flags.Where(f => f.flag1 == Properties.Settings.Default.ARFlag).FirstOrDefault();
if (Properties.Settings.Default.DARFlag != 0) DARFlag = sa.flags.Where(f => f.flag1 == Properties.Settings.Default.DARFlag).FirstOrDefault();
if (Properties.Settings.Default.ConfirmedFlag != 0) ConfirmedFlag = sa.flags.Where(f => f.flag1 == Properties.Settings.Default.ConfirmedFlag).FirstOrDefault();
}
flag aRFlag;
flag dARFlag;
flag confirmedFlag;
public flag ARFlag
{
get
{
return aRFlag;
}
set
{
aRFlag = value;
OnPropertyChanged("ARFlag");
Properties.Settings.Default.ARFlag = aRFlag.flag1;
Properties.Settings.Default.Save();
}
}
public flag DARFlag
{
get
{
return dARFlag;
}
set
{
dARFlag = value;
OnPropertyChanged("DARFlag");
Properties.Settings.Default.DARFlag = dARFlag.flag1;
Properties.Settings.Default.Save();
}
}
public flag ConfirmedFlag
{
get
{
return confirmedFlag;
}
set
{
confirmedFlag = value;
OnPropertyChanged("ConfirmedFlag");
Properties.Settings.Default.ConfirmedFlag = confirmedFlag.flag1;
Properties.Settings.Default.Save();
}
}
public void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
public event PropertyChangedEventHandler PropertyChanged;
}
以及相关的XAML:
<Window.Resources>
<luke:ARDAR x:Key="ARDAR"/>
<luke:ocSAFlags x:Key="ocSAFlags" />
</Window.Resources>
<TabControl>
<TabItem Header="Retention">
<TabControl>
<TabItem Header="Renewals">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition />
</Grid.RowDefinitions>
<ToolBar Grid.Row="0">
<StackPanel Orientation="Horizontal" DataContext="{StaticResource ARDAR}">
<Label Content="AR Flag" />
<ComboBox Width="120"
ItemsSource="{StaticResource ocSAFlags}"
DisplayMemberPath="flag_desc"
SelectedItem="{Binding ARFlag}"
/>
<Label Content="DAR Flag" />
<ComboBox Width="120"
ItemsSource="{StaticResource ocSAFlags}"
DisplayMemberPath="flag_desc"
SelectedItem="{Binding DARFlag}" />
<Label Content="Conf Flag" />
<ComboBox Width="120"
ItemsSource="{StaticResource ocSAFlags}"
DisplayMemberPath="flag_desc"
SelectedItem="{Binding ConfirmedFlag}"/>
</StackPanel>
</ToolBar>
</Grid>
</TabItem>
</TabControl>
</TabItem>
</TabControl>
编辑:我还应该显示提供 ocSAFlags
的代码,以防与解决方案相关。
public class ocSAFlags : ObservableCollection<flag>
{
public ocSAFlags()
{
var sa = new SALinqDataContext();
var flags = sa.flags.Where(f => f.available == true)
.OrderBy(f => f.flag_desc);
foreach (flag f in flags) Add(f);
}
}
阻止 ComboBox
显示信息的问题最终与程序初始化时的加载顺序无关。
真正的问题是我的 XAML 实例化了 ocSAFlags
的一个实例,它填充了 ComboBox
,当 ARDAR
被初始化并设置值 (flag
) 时绑定属性,这些值是等效的,但与实际值不同 flag
。
因此,我的解决方案实际上最终是将 ocSAFlags
设为 Static Class
,并使用它来提供 属性 作为 ComboBoxes
的 ItemsSource
作为以及查找存储在设置中的 ID 的 flag
的 linq 查询的 'source'。
XAML:我从资源中删除了行 <luke:ocSAFlags x:Key="ocSAFlags" />
。我更改了 ItemsSources:ItemsSource="{Binding Source={x:Static luke:ocSAFlags.OCFlag},Mode=OneWay}"
这是静态的 class:
public static class ocSAFlags
{
static private ObservableCollection<flag> oCFlag = getSAFlags();
private static ObservableCollection<flag> getSAFlags()
{
var x = new ObservableCollection<flag>();
var sa = new SALinqDataContext();
var flags = sa.flags.Where(f => f.available == true)
.OrderBy(f => f.flag_desc);
foreach (flag f in flags) x.Add(f);
return x;
}
public static ObservableCollection<flag> OCFlag
{
get
{
return oCFlag;
}
}
}
我有 3 个组合框绑定到名为 ARDAR
的对象,其属性为 ARFlag
、DARFlag
和 ConfirmedFlag
。当从 ComboBox
中选择一个标志时,其 ID 将保存在设置中 (Properties.Settings.Default.ARFlag = aRFlag.flag1;
)。
应用程序启动时,会通过 XAML 创建 ARDAR
对象的实例。对象的构造函数检查非零值的设置,如果有值 (if (Properties.Settings.Default.ARFlag != 0) ARFlag = sa.flags.Where(f => f.flag1 == Properties.Settings.Default.ARFlag).FirstOrDefault();
)
这会触发 OnPropertyChanged
方法,我认为该方法会更新组合框,然后显示已保存设置的选择。但是,在初始化应用程序时,组合框留空。我确保 ARDAR
的属性实际上已更改为其各自的设置,并且 OnPropertyChanged
实际上正在触发。那么,我错过了什么?如何让组合框显示它们保存的设置?
这是我的 XAML & C# 代码:
public class ARDAR : INotifyPropertyChanged
{
public ARDAR()
{
var sa = new SALinqDataContext();
if (Properties.Settings.Default.ARFlag != 0) ARFlag = sa.flags.Where(f => f.flag1 == Properties.Settings.Default.ARFlag).FirstOrDefault();
if (Properties.Settings.Default.DARFlag != 0) DARFlag = sa.flags.Where(f => f.flag1 == Properties.Settings.Default.DARFlag).FirstOrDefault();
if (Properties.Settings.Default.ConfirmedFlag != 0) ConfirmedFlag = sa.flags.Where(f => f.flag1 == Properties.Settings.Default.ConfirmedFlag).FirstOrDefault();
}
flag aRFlag;
flag dARFlag;
flag confirmedFlag;
public flag ARFlag
{
get
{
return aRFlag;
}
set
{
aRFlag = value;
OnPropertyChanged("ARFlag");
Properties.Settings.Default.ARFlag = aRFlag.flag1;
Properties.Settings.Default.Save();
}
}
public flag DARFlag
{
get
{
return dARFlag;
}
set
{
dARFlag = value;
OnPropertyChanged("DARFlag");
Properties.Settings.Default.DARFlag = dARFlag.flag1;
Properties.Settings.Default.Save();
}
}
public flag ConfirmedFlag
{
get
{
return confirmedFlag;
}
set
{
confirmedFlag = value;
OnPropertyChanged("ConfirmedFlag");
Properties.Settings.Default.ConfirmedFlag = confirmedFlag.flag1;
Properties.Settings.Default.Save();
}
}
public void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
public event PropertyChangedEventHandler PropertyChanged;
}
以及相关的XAML:
<Window.Resources>
<luke:ARDAR x:Key="ARDAR"/>
<luke:ocSAFlags x:Key="ocSAFlags" />
</Window.Resources>
<TabControl>
<TabItem Header="Retention">
<TabControl>
<TabItem Header="Renewals">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition />
</Grid.RowDefinitions>
<ToolBar Grid.Row="0">
<StackPanel Orientation="Horizontal" DataContext="{StaticResource ARDAR}">
<Label Content="AR Flag" />
<ComboBox Width="120"
ItemsSource="{StaticResource ocSAFlags}"
DisplayMemberPath="flag_desc"
SelectedItem="{Binding ARFlag}"
/>
<Label Content="DAR Flag" />
<ComboBox Width="120"
ItemsSource="{StaticResource ocSAFlags}"
DisplayMemberPath="flag_desc"
SelectedItem="{Binding DARFlag}" />
<Label Content="Conf Flag" />
<ComboBox Width="120"
ItemsSource="{StaticResource ocSAFlags}"
DisplayMemberPath="flag_desc"
SelectedItem="{Binding ConfirmedFlag}"/>
</StackPanel>
</ToolBar>
</Grid>
</TabItem>
</TabControl>
</TabItem>
</TabControl>
编辑:我还应该显示提供 ocSAFlags
的代码,以防与解决方案相关。
public class ocSAFlags : ObservableCollection<flag>
{
public ocSAFlags()
{
var sa = new SALinqDataContext();
var flags = sa.flags.Where(f => f.available == true)
.OrderBy(f => f.flag_desc);
foreach (flag f in flags) Add(f);
}
}
阻止 ComboBox
显示信息的问题最终与程序初始化时的加载顺序无关。
真正的问题是我的 XAML 实例化了 ocSAFlags
的一个实例,它填充了 ComboBox
,当 ARDAR
被初始化并设置值 (flag
) 时绑定属性,这些值是等效的,但与实际值不同 flag
。
因此,我的解决方案实际上最终是将 ocSAFlags
设为 Static Class
,并使用它来提供 属性 作为 ComboBoxes
的 ItemsSource
作为以及查找存储在设置中的 ID 的 flag
的 linq 查询的 'source'。
XAML:我从资源中删除了行 <luke:ocSAFlags x:Key="ocSAFlags" />
。我更改了 ItemsSources:ItemsSource="{Binding Source={x:Static luke:ocSAFlags.OCFlag},Mode=OneWay}"
这是静态的 class:
public static class ocSAFlags
{
static private ObservableCollection<flag> oCFlag = getSAFlags();
private static ObservableCollection<flag> getSAFlags()
{
var x = new ObservableCollection<flag>();
var sa = new SALinqDataContext();
var flags = sa.flags.Where(f => f.available == true)
.OrderBy(f => f.flag_desc);
foreach (flag f in flags) x.Add(f);
return x;
}
public static ObservableCollection<flag> OCFlag
{
get
{
return oCFlag;
}
}
}