C# WPF和Metro绑定

C# WPF和Metro绑定,c#,wpf,mahapps.metro,C#,Wpf,Mahapps.metro,也许你可以帮我,我已经尝试了几种不同的方法,但我无法达到预期的效果 使用MahApps,我想使用组合框将应用的主题更改为我的WPF窗口 我使用了MahApps演示中的一些代码,并将其应用到我的项目/解决方案中。我可以将主题名称和重音名称加载到项目中的组合框中,但是现在,当我更改这些组合框中的选择时,我希望使用“SelectionChanged”事件中的代码调用“AccentColorMenuData类”中存在的命令 因此,我的基本模型代码是: public abstract class View

也许你可以帮我,我已经尝试了几种不同的方法,但我无法达到预期的效果

使用MahApps,我想使用组合框将应用的主题更改为我的WPF窗口

我使用了MahApps演示中的一些代码,并将其应用到我的项目/解决方案中。我可以将主题名称和重音名称加载到项目中的组合框中,但是现在,当我更改这些组合框中的选择时,我希望使用“SelectionChanged”事件中的代码调用“AccentColorMenuData类”中存在的命令

因此,我的基本模型代码是:

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();
        }
    }
}
最后是控件内组合框的XAML


这就是更改主题/重音的方式

ThemeManager.ChangeAppStyle(Windows.Application.Current, ThemeManager.GetAccent(AccentName), ThemeManager.GetAppTheme(ThemeName))
您已经在AccentColorMenuData和AppThemeMenuData的更改主题中使用了它:AccentColorMenuData

更新/编辑: 下面是我如何实现这类功能的。它在VB中,但如果需要,您可以轻松地转换它。作为设置的一部分,Mine位于主窗口上的弹出按钮中:

要求您在项目中创建设置,以使此颜色信息在会话中保持不变。你可以在VSB中打开我的项目并选择设置。您可以添加以下设置:

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();


        }

    }
  • Name=applicationthename Type=String Scope=User Value=BaseDark

  • Name=ApplicationAccentName Type=String Scope=User Value=Blue

当然,您可以将默认值设置为任意值

新对象:

Public Class ApplicationAccentColor
    Public Property Name As String
    Public Property ColorBrush As SolidColorBrush
End Class
在您的viewModel中------------------------

道具:

Public Property AppThemes As New List(Of AppTheme)

Public Property AccentColors As New List(Of ApplicationAccentColor)

Public Property SelectedTheme As AppTheme
    Get
        Return ThemeManager.GetAppTheme(MySettings.Default.ApplicationThemeName)
    End Get
    Set
        If ThemeManager.GetAppTheme(MySettings.Default.ApplicationThemeName) Is Value Then Exit Property
        MySettings.Default.ApplicationThemeName = value.Name
        MySettings.Default.Save()
        ThemeManager.ChangeAppStyle(Windows.Application.Current, ThemeManager.GetAccent(SelectedAccent.Name), ThemeManager.GetAppTheme(value.Name))
    End Set
End Property

Public Property SelectedAccent As ApplicationAccentColor
    Get
        For Each acc As ApplicationAccentColor In From acc1 In AccentColors Where acc1.Name = MySettings.Default.ApplicationAccentName
            Return acc
        Next
        Return New ApplicationAccentColor()
    End Get
    Set
        If ThemeManager.GetAccent(MySettings.Default.ApplicationAccentName).Name is value.Name Then Exit Property
        MySettings.Default.ApplicationAccentName = value.Name
        MySettings.Default.Save()
        ThemeManager.ChangeAppStyle(Windows.Application.Current, ThemeManager.GetAccent(value.Name), ThemeManager.GetAppTheme(SelectedTheme.Name))
    End Set
End Property
建造商:

AppThemes = ThemeManager.AppThemes
AccentColors = ThemeManager.Accents.Select(Function(a) New ApplicationAccentColor With {.Name = a.Name, .ColorBrush = a.Resources("AccentColorBrush")}).ToList()
XAML:

控制资源:

<DataTemplate x:Key="AppThemeItemsTemplate">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="20"/>
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>
        <Ellipse Grid.Column="0" Width="20" Height="20" Fill="{Binding Resources[WhiteColorBrush]}" Stroke="{Binding Resources[BlackColorBrush]}"/>
        <Label Grid.Column="1" Content="{Binding Name}"/>
    </Grid>
</DataTemplate>

<DataTemplate x:Key="AccentColorItemsTemplate">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="20"/>
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>
        <Ellipse Grid.Column="0" Width="20" Height="20" Fill="{Binding ColorBrush}"/>
        <Label Grid.Column="1" Content="{Binding Name}"/>
    </Grid>
</DataTemplate>

实际控制:

        <StackPanel Margin="10">
            <Label Content="Theme"/>
            <ComboBox Width="125" HorizontalContentAlignment="Left" HorizontalAlignment="Left" ItemTemplate="{StaticResource AppThemeItemsTemplate}" ItemsSource="{Binding AppThemes}" SelectedItem="{Binding SelectedTheme}"/>
            <Label Content="Accent"/>
            <ComboBox Width="125" HorizontalContentAlignment="Left" HorizontalAlignment="Left" ItemTemplate="{StaticResource AccentColorItemsTemplate}" ItemsSource="{Binding AccentColors}" SelectedItem="{Binding SelectedAccent}"/>
            <Button Style="{StaticResource AccentedSquareButtonStyle}" Command="{Binding RefreshDirectoriesFiles}" Margin="0,20,0,0" Content="Refresh Directories/Files"/>
        </StackPanel>


谢谢,我在原始帖子中做了一个更新,请看一下这两种方法,你认为什么是最好的(我试图重写相同的代码),以及为什么在我尝试连续第二次更改后主题没有改变。不使用代码隐藏,你可以真正简化一切。另外,您是否计划在会话中保持颜色,还是用户每次启动应用程序时都必须更改颜色?是的,保存应用的主题和颜色会很好。抱歉。。这就是LINQ。对于每个acc,如果acc.Name=MySettings.Default.ApplicationAccentName,则返回acc End,如果下次返回新的ApplicationAccentColor()
Public Class ApplicationAccentColor
    Public Property Name As String
    Public Property ColorBrush As SolidColorBrush
End Class
Public Property AppThemes As New List(Of AppTheme)

Public Property AccentColors As New List(Of ApplicationAccentColor)

Public Property SelectedTheme As AppTheme
    Get
        Return ThemeManager.GetAppTheme(MySettings.Default.ApplicationThemeName)
    End Get
    Set
        If ThemeManager.GetAppTheme(MySettings.Default.ApplicationThemeName) Is Value Then Exit Property
        MySettings.Default.ApplicationThemeName = value.Name
        MySettings.Default.Save()
        ThemeManager.ChangeAppStyle(Windows.Application.Current, ThemeManager.GetAccent(SelectedAccent.Name), ThemeManager.GetAppTheme(value.Name))
    End Set
End Property

Public Property SelectedAccent As ApplicationAccentColor
    Get
        For Each acc As ApplicationAccentColor In From acc1 In AccentColors Where acc1.Name = MySettings.Default.ApplicationAccentName
            Return acc
        Next
        Return New ApplicationAccentColor()
    End Get
    Set
        If ThemeManager.GetAccent(MySettings.Default.ApplicationAccentName).Name is value.Name Then Exit Property
        MySettings.Default.ApplicationAccentName = value.Name
        MySettings.Default.Save()
        ThemeManager.ChangeAppStyle(Windows.Application.Current, ThemeManager.GetAccent(value.Name), ThemeManager.GetAppTheme(SelectedTheme.Name))
    End Set
End Property
AppThemes = ThemeManager.AppThemes
AccentColors = ThemeManager.Accents.Select(Function(a) New ApplicationAccentColor With {.Name = a.Name, .ColorBrush = a.Resources("AccentColorBrush")}).ToList()
<DataTemplate x:Key="AppThemeItemsTemplate">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="20"/>
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>
        <Ellipse Grid.Column="0" Width="20" Height="20" Fill="{Binding Resources[WhiteColorBrush]}" Stroke="{Binding Resources[BlackColorBrush]}"/>
        <Label Grid.Column="1" Content="{Binding Name}"/>
    </Grid>
</DataTemplate>

<DataTemplate x:Key="AccentColorItemsTemplate">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="20"/>
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>
        <Ellipse Grid.Column="0" Width="20" Height="20" Fill="{Binding ColorBrush}"/>
        <Label Grid.Column="1" Content="{Binding Name}"/>
    </Grid>
</DataTemplate>
        <StackPanel Margin="10">
            <Label Content="Theme"/>
            <ComboBox Width="125" HorizontalContentAlignment="Left" HorizontalAlignment="Left" ItemTemplate="{StaticResource AppThemeItemsTemplate}" ItemsSource="{Binding AppThemes}" SelectedItem="{Binding SelectedTheme}"/>
            <Label Content="Accent"/>
            <ComboBox Width="125" HorizontalContentAlignment="Left" HorizontalAlignment="Left" ItemTemplate="{StaticResource AccentColorItemsTemplate}" ItemsSource="{Binding AccentColors}" SelectedItem="{Binding SelectedAccent}"/>
            <Button Style="{StaticResource AccentedSquareButtonStyle}" Command="{Binding RefreshDirectoriesFiles}" Margin="0,20,0,0" Content="Refresh Directories/Files"/>
        </StackPanel>