【发布时间】:2016-09-21 05:51:38
【问题描述】:
也许你可以帮忙,我已经尝试了几种不同的方法,但我无法达到预期的结果......
使用 MahApps,我想使用 ComboBoxes 将应用的主题更改为我的 WPF 窗口。
我使用了 MahApps Demo 中的一些代码并适应了我的项目/解决方案。我可以将主题名称和重音名称加载到我的项目中的组合框,但是现在,当我更改这些组合框中的选择时,我想使用“SelectionChanged”中的代码调用“AccentColorMenuData 类”中存在的命令事件。
所以我的 BaseModel 代码是:
public abstract class ViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged([CallerMemberName] string propertyName = "")
{
Debug.Write($"--- CLASS ViewModel Called OnPropertyChanged for object: {propertyName} -------- \n");
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
我的 ViewModel 是:
namespace WPFApplication.Ui
{
public class AccentColorMenuData
{
public string Name { get; set; }
public Brush BorderColorBrush { get; set; }
public Brush ColorBrush { get; set; }
private ICommand changeAccentCommand;
public ICommand ChangeAccentCommand
{
get { return this.changeAccentCommand ??
(changeAccentCommand = new SimpleCommand { CanExecuteDelegate = x => true, ExecuteDelegate = x => this.DoChangeTheme(x) }); }
}
protected virtual void DoChangeTheme(object sender)
{
var theme = ThemeManager.DetectAppStyle(Application.Current);
var accent = ThemeManager.GetAccent(this.Name);
ThemeManager.ChangeAppStyle(Application.Current, accent, theme.Item1);
}
}
public class AppThemeMenuData : AccentColorMenuData
{
protected override void DoChangeTheme(object sender)
{
var theme = ThemeManager.DetectAppStyle(Application.Current);
var appTheme = ThemeManager.GetAppTheme(this.Name);
ThemeManager.ChangeAppStyle(Application.Current, theme.Item2, appTheme);
}
}
public class RemoteSystemsViewModel : ViewModel
{
public List<AccentColorMenuData> AccentColors { get; set; }
public List<AppThemeMenuData> AppThemes { get; set; }
public RemoteSystemsViewModel()
{
// create accent color menu items for the demo
this.AccentColors = ThemeManager.Accents
.Select(a => new AccentColorMenuData() { Name = a.Name, ColorBrush = a.Resources["AccentColorBrush"] as Brush })
.ToList();
// create metro theme color menu items for the demo
this.AppThemes = ThemeManager.AppThemes
.Select(a => new AppThemeMenuData() { Name = a.Name, BorderColorBrush = a.Resources["BlackColorBrush"] as Brush, ColorBrush = a.Resources["WhiteColorBrush"] as Brush })
.ToList();
}
}
}
我的控件代码在后面(注意我已经有两个组合框的事件函数)
public partial class ConfigurationView : UserControl
{
private readonly RemoteSystemsViewModel _viewModel;
public RemoteSystemsView()
{
_viewModel = new RemoteSystemsViewModel();
InitializeComponent();
DataContext = _viewModel;
}
void SelectionChanged(object sender, SelectionChangedEventArgs e)
{
}
}
最后是我的 XAML 用于控件内的组合框
ComboBox x:Name="AccentColorsComboBox"
ItemsSource="{Binding AccentColors, Mode=OneWay}"
SelectedValuePath="Name"
DisplayMemberPath="Name"
SelectionChanged="SelectionChanged"
/>
<ComboBox x:Name="AppThemesComboBox"
ItemsSource="{Binding AppThemes, Mode=OneWay}"
SelectedValuePath="Name"
DisplayMemberPath="Name"
SelectionChanged="SelectionChanged"
>
</ComboBox>
正如我所说,组合框填充了正确的信息,但是现在,当我更改 1 或其他时,我想修改应用的主题。
我已经尝试了许多不同的方法来实现这一点,但都没有成功,也许你可以伸出援助之手...... :)
谢谢。
更新:使用达斯汀的建议
void SelectionChanged(object sender, SelectionChangedEventArgs e)
{
string AccentName = this.AccentColorsComboBox.SelectedValue as string;
string ThemeName = this.AppThemesComboBox.SelectedValue as string;
if (!string.IsNullOrEmpty(AccentName) && !string.IsNullOrEmpty(ThemeName))
{
//Debug.Write($"{AccentName} - {ThemeName}\n");
ThemeManager.ChangeAppStyle(Application.Current, ThemeManager.GetAccent(AccentName), ThemeManager.GetAppTheme(ThemeName));
}
}
同时我也做到了:
void SelectionChanged(object sender, SelectionChangedEventArgs e)
{
ComboBox control = (ComboBox)sender;
String name = control.Name;
int index = -1;
index = control.SelectedIndex;
if (index > -1)
{
var vm = this.DataContext as RemoteSystemsViewModel;
if (name == "AccentColorsComboBox")
{
//Call command from viewmodel
if ((vm != null) && (vm.AccentColors[index].ChangeAccentCommand.CanExecute(null)))
vm.AccentColors[index].ChangeAccentCommand.Execute(null);
}
else
{
//Call command from viewmodel
if ((vm != null) && (vm.AppThemes[index].ChangeAccentCommand.CanExecute(null)))
vm.AppThemes[index].ChangeAccentCommand.Execute(null);
}
}
}
现在我对这两种方法的问题是,当我尝试连续 2 次更改主题时,如果我更改一次,它只会更改主题,然后返回并进行另一个选择并再次更改...口音在一开始就可以更改试试看。
有什么想法吗?
C# 中的更新/解决方案(感谢 DUSTIN 的帮助)
对于 XAML 和 CONTROLS,代码与 Dustin 在他的帖子中发布的代码相同。
对于 C# 来说:
新对象:
public class ApplicationAccentColor
{
public string Name { get; set; }
public SolidColorBrush ColorBrush { get; set; }
}
视图模型 + 构造器:
public class SystemsViewModel : ViewModel
{
/// Open Project Settings and select Settings, then add the following values:
/// Name= ApplicationThemeName Type = String Scope= User Value = BaseDark
/// Name= ApplicationAccentName Type = String Scope= User Value = Blue
/// </summary>
public IEnumerable<AppTheme> AppThemes { get; set; }
public IEnumerable<ApplicationAccentColor> AccentColors { get; set; }
public AppTheme SelectedTheme
{
/// Project Global Settings variable
/// Name= ApplicationThemeName Type = String Scope= User Value = BaseDark
/// Name= ApplicationAccentName Type = String Scope= User Value = Blue
get
{
/// Get default Values from global varable settings
return ThemeManager.GetAppTheme(Settings.Default.ApplicationThemeName);
}
set
{
/// Get default Values from global varable settings, and check if they are the same
if (object.ReferenceEquals(ThemeManager.GetAppTheme(Settings.Default.ApplicationThemeName), value))
return;
/// Save the new value to global settings variable
Settings.Default.ApplicationThemeName = value.Name;
Settings.Default.Save();
/// Apply the Theme
ThemeManager.ChangeAppStyle(Application.Current, ThemeManager.GetAccent(SelectedAccent.Name), ThemeManager.GetAppTheme(value.Name));
}
}
public ApplicationAccentColor SelectedAccent
{
/// Project Global Settings variable
/// Name= ApplicationThemeName Type = String Scope= User Value = BaseDark
/// Name= ApplicationAccentName Type = String Scope= User Value = Blue
get
{
//foreach (ApplicationAccentColor acc in AccentColors)
//{
// if (acc.Name == Settings.Default.ApplicationAccentName)
// {
// return acc;
// }
//}
//return new ApplicationAccentColor();
/// Get default Values from global varable settings
foreach (ApplicationAccentColor acc in from acc1 in AccentColors where acc1.Name == Settings.Default.ApplicationAccentName select acc1)
{
return acc;
}
return new ApplicationAccentColor();
}
set
{
/// Get default Values from global varable settings, and check if they are the same
if (object.ReferenceEquals(ThemeManager.GetAccent(Settings.Default.ApplicationAccentName).Name, value.Name))
return;
/// Save the new value to global settings variable
Settings.Default.ApplicationAccentName = value.Name;
Settings.Default.Save();
/// Apply the Theme
ThemeManager.ChangeAppStyle(Application.Current, ThemeManager.GetAccent(value.Name), ThemeManager.GetAppTheme(SelectedTheme.Name));
}
}
public SystemsViewModel()
{
AppThemes = ThemeManager.AppThemes;
AccentColors = ThemeManager.Accents.Select(a => new ApplicationAccentColor
{
Name = a.Name,
ColorBrush = (SolidColorBrush)a.Resources["AccentColorBrush"]
}).ToList();
}
}
APP.cs(在启动时加载最新设置)
//Loading Values from Global Variables set in Application Settings
ThemeManager.ChangeAppStyle(Application.Current,
ThemeManager.GetAccent(Settings.Default.ApplicationAccentName.ToString()),
ThemeManager.GetAppTheme(Settings.Default.ApplicationThemeName.ToString()));
感谢达斯汀的帮助 :)
【问题讨论】:
标签: c# wpf mahapps.metro