1

I try to change the Button icon by Click_Event, So currently I have the xaml like this:

<Button Content="{materialDesign:PackIcon LanDisconnect}" Command="{Binding Connect}" />

And in the ViewModel:

public ICommand Connect
{
    get
    {
        _Connect = new RelayCommand(
            param => ConnectChip());
        return _Connect;
    }
}

How should I change the Button icon to {MaterialDesign:PackIcon LanConnect} in Command Connect? Thanks!

mm8
  • 163,881
  • 10
  • 57
  • 88
BarryLib
  • 299
  • 1
  • 5
  • 20
  • You should look at [Buttons.xaml](https://github.com/ButchersBoy/MaterialDesignInXamlToolkit/blob/master/MainDemo.Wpf/Buttons.xaml) in the MainDemo.Wpf project of the MaterialDesignInXamlToolkit – KiwiPiet Aug 08 '17 at 01:46
  • Also assign your _Connect field outside the get or check if it is null before assigning a new RelayCommand. Your code as it is will create a new command everytime the get is called – KiwiPiet Aug 08 '17 at 01:55
  • I don't think this is the best way of doing it. A command should be used to cause an action like say, Save or Cancel. Change in UI elements appearance should be done through control template and in your case, maybe an event trigger. – Shakti Prakash Singh Aug 08 '17 at 02:01
  • 2
    There should be one or more DataTriggers on a view model property which is changed by the command. Depending on the value of that property the DataTriggers would set the Button Content to different values. – Clemens Aug 08 '17 at 05:43

2 Answers2

4

While some of the comments suggest slightly more advanced solutions (e.g. using DataTriggers). I would suggest (at least to start with) you simply need to add a binding for the button content. Then you can add a property to the view-model and update it via the command.

In your case you are using Material Design content.

So in your view-model, you would want to include an icon property:

using MaterialDesignThemes.Wpf;

public PackIconKind IconKind
{
    get { return _IconKind; }
    set { SetField(ref _IconKind, value); }
}
private PackIconKind _IconKind = PackIconKind.LanDisconnect;

See this reference for the SetField method

Then change your button XAML to this:

<Button Command="{Binding MyCommand}" Width="100" Height="32">
    <materialDesign:PackIcon Kind="{Binding IconKind}" />
</Button>

This sets up the binding for your icon in the button. Now the view-model can change this Kind whenever it wants. I prefer to setup commands in the constructor. I first have a command property as follows:

public ICommand MyCommand { get; }

and in the constructor:

MyCommand = new RelayCommand(UpdateIcon);

then add the UpdateIcon method in to the view-model. This method can then be called from other places (not just the button command).

protected void UpdateIcon()
{
    IconKind = MaterialDesignThemes.Wpf.PackIconKind.LanConnect;
}
Ben
  • 3,241
  • 4
  • 35
  • 49
3

You could bind the Content property of the Button to a PackIcon property that you set to a new value in your ConnectChip() method.

XAML:

<Button Content="{Binding Icon}" Command="{Binding Connect}" />

View Model:

public class ViewModel : INotifyPropertyChanged
{
    private ICommand _Connect;
    public ICommand Connect
    {
        get
        {
            _Connect = new RelayCommand(
                param => ConnectChip());
            return _Connect;
        }
    }

    private PackIcon _icon = new PackIcon { Kind = PackIconKind.LanDisconnect };
    public PackIcon Icon
    {
        get { return _icon; }
        set { _icon = value; NotifyPropertyChanged(); }
    }

    private void ConnectChip()
    {
        //change icon:
        Icon = new PackIcon { Kind = PackIconKind.Airballoon };
    }

    public event PropertyChangedEventHandler PropertyChanged;
    private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
}
mm8
  • 163,881
  • 10
  • 57
  • 88
  • While this is a reasonable answer, it would be better to bind to the PackIcon Kind property (as in my answer), this would allow the button to be more easily extended later with other content such as text. – Ben Aug 08 '17 at 09:34
  • 1
    You mean in the answer you *edited* based on mine? The original one included a Uri property. – mm8 Aug 08 '17 at 09:35
  • This is not true – Ben Aug 08 '17 at 09:36
  • Which part is not true? – mm8 Aug 08 '17 at 09:36
  • mm8, I realise that it looks like this is what happened, and I have no way to prove it, but the OP stated that they wanted the button command to update the MaterialDesign:PackIcon. My first attempt at this answer was prematurely posted. The question was 8 hours old so I thought I had time to fix it. I investigated how to bind to the PackIcon and then I updated my asnwer - unfortunately as I saved my edits, your answer then appeared. – Ben Aug 08 '17 at 09:39
  • 1
    No worries :) Two answers are better than none. – mm8 Aug 08 '17 at 09:42