【问题标题】:WPF and Metro BindingWPF 和 Metro 绑定
【发布时间】: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


    【解决方案1】:

    这是您更改主题/口音的方式

    ThemeManager.ChangeAppStyle(Windows.Application.Current, ThemeManager.GetAccent(AccentName), ThemeManager.GetAppTheme(ThemeName))
    

    您已经在 AccentColorMenuData 和 AppThemeMenuData 的 DoChangeTheme 中使用它:AccentColorMenuData

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

    要求您在项目中创建设置,以便此颜色信息在会话中持续存在。您可以在 VS b 中打开我的项目并选择设置。您添加以下设置:

    • Name= ApplicationThemeName 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。
    • For Each acc As ApplicationAccentColor In AccentColors If acc.Name = MySettings.Default.ApplicationAccentName Then Return acc End If Next Return New ApplicationAccentColor()
    猜你喜欢
    • 2012-03-25
    • 1970-01-01
    • 2011-06-25
    • 2014-01-10
    • 1970-01-01
    • 2010-12-17
    • 2011-05-18
    • 2012-12-28
    • 1970-01-01
    相关资源
    最近更新 更多