0

I'm trying to create a WPF UserControl which contains 2 buttons. I use this UserControl in a Window and apply a Window.Resource value to set the background of one button inside the user control.

Currently I have:

  • window.xaml

    <Window.Resources>
        <SolidColorBrush Color="Brown" x:Key="theBG"></SolidColorBrush>
    </Window.Resources>
    <theControl:TheControl  
        x:Name="TheControl" 
        buttonBG="{Binding Source={StaticResource theBG}}" />
    
  • usercontrol.xaml.cs

    public SolidColorBrush buttonBG
    {
        get { return base.GetValue(buttonBGProperty) as SolidColorBrush; }
        set { base.SetValue(buttonBGProperty, value); }
    }
    public static readonly DependencyProperty buttonBGProperty = DependencyProperty.Register("buttonBG", typeof(SolidColorBrush), typeof(DataPanel), null);
    
  • usercontrol.xaml

    <Button ... Background="{Binding buttonBG}">
    

I was expecting this to work but the background is not the one I set in the window resource.

What am I doing wrong?

ASh
  • 34,632
  • 9
  • 60
  • 82
Sabin Neagu
  • 712
  • 7
  • 15
  • 1
    You can simplify `buttonBG="{Binding Source={StaticResource theBG}}" ` to `buttonBG="{StaticResource theBG}"`, the binding does nothing. – H.B. Jun 23 '16 at 13:50
  • 1
    `SolidColorBrush` in unnecessarily specific, would just use `Brush` as property type. – H.B. Jun 23 '16 at 13:52

2 Answers2

1
Background="{Binding buttonBG}"

Implies either that you changed the DataContext of the UserControl, which you should never do. Or that the binding is just wrong.

Use

Background="{Binding buttonBG, ElementName=control}"

Naming your UserControl root element control. RelativeSource works as well.

Community
  • 1
  • 1
H.B.
  • 166,899
  • 29
  • 327
  • 400
  • could this be implemented without the use of DependencyProperties? – Sabin Neagu Jun 23 '16 at 13:59
  • Yes, but then you loose binding support. Properties on UserControls should usually be dependency properties to allow every use case. – H.B. Jun 23 '16 at 14:15
1

Try placing it in a separate model or even a viewmodel that has INotifyPropertyChanged. When you add view code in the cs for an xaml file, you need to bind with relativesource self and its hacky and goes against MVVM. I would create a seperate ViewModel with a Brush that has NotifyPropertyChanged baked into it. This will tell the UI to change everything its bound to on value change.

In the Window, bind your viewmodel to datacontext. In the viewmodel you can put:

    private Brush _bgColor;
    public Brush BgColor 
   {
      get{return _bgColor;
    }
    set
    {
     _bgColor = value;
     OnPropertyChanged("BgColor");
   }

Create an ICommand, and bind your button to it like this in the viewmodel:

ICommand ChangeBgColor {get;set;

And in the XAML for the Button:

 Command="{Binding Path=DataContext.ChangeBgColor,RelativeSource={RelativeSorce Mode=FindAncestor,AncestorType={x:Type UserControl}}"

This will fire the ICommand, bound to the viewmodel that is the datacontex of the window that you are working with.

And in that code for the ICommand change out your colors, you could do it like this:

private void OnChangeBgColor(object param){
 var bc = new BrushConverter();
 BgColor = (Brush)bc.ConvertFrom("#fff");
}

With the MVVM pattern, you want to get away from putting unnecessary code in the xaml.cs files and start putting them into viewmodels and models.

Kevin B Burns
  • 1,032
  • 9
  • 24