Understanding Commands in WPF: A Cleaner Alternative to Button Click Events

Many WPF developers start by using Button Click events for handling user actions. At first, this seems simple and straightforward. But very soon, the code-behind file becomes huge , and maintaining it turns into a challenge. One big problem arises: when the logic changes, the button does not enable or disable automatically , and testing button click logic becomes very difficult. So the big question is: Is there a better way to handle button actions in WPF? The answer is Commands . In this post, we’ll learn how to use Commands in WPF with a simple, practical example. We’ll cover: What a Command is How it works Why using Commands is better than Click events How buttons can automatically enable or disable based on conditions What is a Command in WPF? In WPF, a Command acts as a middle layer between the UI and your logic. Instead of the button directly calling a method, it triggers a Command , and the Command decides: What code should run Whether the button s...

How to apply theme and color in wpf Metro window application

In this example i am using Prism,unity and MahApps make sure you are also using same otherwise you will not get PrismApplication,BindableBase and MetroWindow.

 MainWindow.xaml

 <metro:MetroWindow x:Class="WpfApplication.Views.MainWindow"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             xmlns:local="clr-namespace:WpfApplication"
             mc:Ignorable="d"
             xmlns:metro="http://metro.mahapps.com/winfx/xaml/controls"
             xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
             Title="Welcome To Metro ui with Prism Unity">
     <metro:MetroWindow.RightWindowCommands>
         <metro:WindowCommands>
             <ComboBox ItemsSource="{Binding LstTheme}" SelectedItem="{Binding SelectedTheme}" Width="100" Background="Transparent" BorderBrush="Transparent">
                 <i:Interaction.Triggers>
                     <i:EventTrigger EventName="SelectionChanged">
                         <i:InvokeCommandAction Command="{Binding DataContext.ApplyThemeCommand,RelativeSource={RelativeSource AncestorType={x:Type ComboBox}}}"/>
                     </i:EventTrigger>
                 </i:Interaction.Triggers>
                 <ComboBox.ItemTemplate>
                     <DataTemplate>
                         <StackPanel Orientation="Horizontal">
                             <Ellipse Width="20" Height="20" Fill="{Binding Value}"/>
                             <TextBlock Text="{Binding Name}" Margin="5" VerticalAlignment="Center"/>
                         </StackPanel>
                     </DataTemplate>
                 </ComboBox.ItemTemplate>
             </ComboBox>
             <ComboBox ItemsSource="{Binding LstColor}" SelectedItem="{Binding SelectedColor}" Width="100" Background="Transparent" BorderBrush="Transparent">
                 <i:Interaction.Triggers>
                     <i:EventTrigger EventName="SelectionChanged">
                         <i:InvokeCommandAction Command="{Binding DataContext.ApplyColorCommand,RelativeSource={RelativeSource AncestorType={x:Type ComboBox}}}"/>
                     </i:EventTrigger>
                 </i:Interaction.Triggers>
                 <ComboBox.ItemTemplate>
                     <DataTemplate>
                         <StackPanel Orientation="Horizontal">
                             <Ellipse Width="20" Height="20" Fill="{Binding Value}"/>
                             <TextBlock Text="{Binding Name}" Margin="5" VerticalAlignment="Center"/>
                         </StackPanel>
                     </DataTemplate>
                 </ComboBox.ItemTemplate>
             </ComboBox>
         </metro:WindowCommands>


     </metro:MetroWindow.RightWindowCommands>
     <StackPanel Orientation="Vertical" HorizontalAlignment="Center" VerticalAlignment="Center">
         <!--here i used DynamicResource for Foreground/Background because i want to dynamically change the color-->
         <TextBlock Height="30" Width="200" Text="This is TextBlock" Margin="5" Foreground="{DynamicResource AccentBaseColorBrush}"/>
         <Button Content="This is Button" HorizontalAlignment="Left" Width="200" Background="{DynamicResource AccentBaseColorBrush}"/>
     </StackPanel>
 </metro:MetroWindow>

 MainWindow.xaml.cs

   public partial class MainWindow : MetroWindow
     {
         public MainWindow()
         {
             InitializeComponent();
             DataContext = new MainWindowViewModel();
         }

     }


 MainWindowViewModel.cs

 public class MainWindowViewModel : BindableBase
    {

        public MainWindowViewModel()
        {
            ApplyThemeCommand = new DelegateCommand(ApplyTheme);
            ApplyColorCommand = new DelegateCommand(ApplyColor);

            _lstTheme = new ObservableCollection<NameValue>()
            {
                new NameValue() {Name = "Light", Value = "White"},
                new NameValue() {Name = "Dark", Value = "Black"}
            };

            SelectedTheme = LstTheme[0];

            _lstColor = new ObservableCollection<NameValue>()
            {
                new NameValue() {Name = "blue", Value = "#2196F3"},
                new NameValue() {Name = "red", Value = "#e52400"},
                new NameValue() {Name = "green", Value = "#60a917"},

                new NameValue() {Name = "purple", Value = "#800080"},
                new NameValue() {Name = "orange", Value = "#fa6800"}

            };

            SelectedColor = _lstColor[0];
        }

        private void ApplyColor()
        {
            ApplyThemeColor();
        }

        private void ApplyTheme()
        {
            ApplyThemeColor();
        }
        private void ApplyThemeColor()
        {
            try
            {
                var accent = SelectedColor.Name ?? LstColor[0].Name;
                var theme = SelectedTheme.Name ?? LstTheme[0].Name;
                Accent newAccent = ThemeManager.GetAccent(accent);
                AppTheme newTheme = ThemeManager.GetAppTheme("Base" + theme);
                ThemeManager.ChangeAppStyle(Application.Current, newAccent, newTheme);
            }
            catch (System.Exception ex)
            {


            }
        }


        private ObservableCollection<NameValue> _lstTheme;

        public ObservableCollection<NameValue> LstTheme
        {
            get { return _lstTheme; }
            set { SetProperty(ref _lstTheme, value); }
        }


        private ObservableCollection<NameValue> _lstColor;

        public ObservableCollection<NameValue> LstColor
        {
            get { return _lstColor; }
            set { SetProperty(ref _lstColor, value); }
        }
        private NameValue _selectedColor;

        public NameValue SelectedColor
        {
            get { return _selectedColor; }
            set { SetProperty(ref _selectedColor, value); }
        }

        private NameValue _selectedTheme;

        public NameValue SelectedTheme
        {
            get { return _selectedTheme; }
            set { SetProperty(ref _selectedTheme, value); }
        }

        public ICommand ApplyThemeCommand { get; set; }
        public ICommand ApplyColorCommand { get; set; }

    }

 NameValue.cs

  public class NameValue : BindableBase
     {

         private string _name;

         public string Name
         {
             get { return _name; }
             set { SetProperty(ref _name, value); }
         }
         private string _value;

         public string Value
         {
             get { return _value; }
             set { SetProperty(ref _value, value); }
         }

     }


 App.xaml

 <prism:PrismApplication x:Class="WpfApplication.App"
              xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
              xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
              xmlns:local="clr-namespace:WpfApplication"
              xmlns:prism="http://prismlibrary.com/">
     <Application.Resources>
         <ResourceDictionary>
             <ResourceDictionary.MergedDictionaries>

                 <!-- MahApps.Metro resource dictionaries. Make sure that all file names are Case Sensitive! -->
                 <ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Controls.xaml"/>

                 <ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Fonts.xaml"/>
                 <ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Colors.xaml"/>

                 <!-- Accent and AppTheme setting -->
                 <ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Accents/Blue.xaml" />
                 <ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Accents/BaseLight.xaml" />
             </ResourceDictionary.MergedDictionaries>
         </ResourceDictionary>
     </Application.Resources>
 </prism:PrismApplication>

 App.xaml.cs

  public partial class App : PrismApplication
     {
         IUnityContainer _container;
         protected override Window CreateShell()
         {
             return _container.Resolve<MainWindow>();
         }
         protected override void RegisterTypes(IContainerRegistry containerRegistry)
         {
             _container = containerRegistry.GetContainer();
         }
     }




Dark themes

Light theme






Comments

Popular posts from this blog

Filter DataGrid and ListView in wpf using ICollectionView

Pagination of DataGrid in WPF using MVVM

How to Create TabControl using Prism Region