1

I'm trying to create my own, very simple, Usercontrol in WPF. It's basically just a Combobox, with some additional Logic in it. I tried to create my own Depdency-Property using this Tutorial: http://www.codeproject.com/Articles/140620/WPF-Tutorial-Dependency-Property

This is working fine so far, but if the property changes, I'd like to reflect this on the Combobox in the User-Control as well. It seems like I can't bind the subcontrol directly to my new Dependency-Project.

My code is looking like this at the moment:

public partial class ClassSelector : UserControl
{
    public static readonly DependencyProperty CurrentValueProperty =
 DependencyProperty.Register("CurrentValue", typeof(ClassType),
 typeof(ClassSelector), new FrameworkPropertyMetadata());

    public ClassType CurrentValue
    {
        get
        {
            return  (ClassType)this.GetValue(CurrentValueProperty);
        }
        set
        {
            this.SetValue(CurrentValueProperty, value);
        }
    }

    public ClassSelector()
    {
        this.DataContext = this;
        InitializeComponent();
        cmbClassType.ItemsSource = Enum.GetValues(typeof(ClassType));
    }
}

Setting the value of the dependy-property or the Combobox seems weirds to me. I tried to bind it direclty in the xaml via:

<Grid>
    <ComboBox x:Name="cmbClassType" SelectedItem="{Binding Path=CurrentValue, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" SelectionChanged="cmbClassType_SelectionChanged" />
</Grid>

I tried to map the Dependicy-Project changed Event with the combobox and visa versa, but this leads to very strange code, since the combobox change would have to change the property-value and the property-value the combobox.

I'm quite sure there has to be a possibility to bind a DependencyProperty to a subcontrol, but I can't find a way to make this work.

Thanks in advance for all advices guys and have a nice weekend

Matthias

Edith says: The calling Window needs to bind the Object to the Grid, not to the Window, so for example:

grdMain.DataContext = new DeckSearch();

is working fine, meanwhile

this.DataContext = new DeckSearch();

This behavior is ONLY at my custom control, all other controls worked perfectly fine with the DataContext on the Window itself.

Matthias Müller
  • 3,336
  • 3
  • 33
  • 65
  • Don't `this.DataContext = this`. That's sinful and filthy and wrong and the devil's going to eat your Visual Studio if you do that. – Federico Berasategui Aug 15 '14 at 19:29
  • If I set it, the Combobox binds to the default value of enum. If I remove it, it keeps being empty, which is even worse. – Matthias Müller Aug 15 '14 at 19:41
  • What HighCore means is that you should name the `Grid`, e.g. with `x:Name="root"`, and set the `DataContext` on it: `root.DataContext = this`. As for your issue I don't get it as I'm able to select a value from the `ComboBox` and it's correctly updated. Could you please show more code or a way to reproduce? – Pragmateek Aug 15 '14 at 19:44
  • Hi Thanks for the response, I'm using the DataContext without knowing exactly what's happening. I guess I will have to read some stuff about it, but thanks for the input. About the Control: Did you try to set the Control on a Window and to bind the new "CurrentValue" property? It keeps being empty at my part, but I get the DependencyProperty-changed event – Matthias Müller Aug 16 '14 at 11:32

1 Answers1

1

Okay so here I fixed your code and it is working at my end

UserControlCodeBehind

public partial class ClassSelector : UserControl
{
    public static readonly DependencyProperty CurrentValueProperty = DependencyProperty.Register("CurrentValue", typeof(ClassType),
        typeof(ClassSelector), new FrameworkPropertyMetadata()
            {
                DefaultValue = ClassType.Type1,
                BindsTwoWayByDefault = true,
                PropertyChangedCallback = CurrentValueChanged,
                DefaultUpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged
            });


    private static void CurrentValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var obj = (ClassSelector)d;
        obj.cmbClassType.SelectedValue = e.NewValue;
    }

    public ClassType CurrentValue
    {
        get
        {
            return (ClassType)this.GetValue(CurrentValueProperty);
        }
        set
        {
            this.SetValue(CurrentValueProperty, value);
        }
    }

    public ClassSelector()
    {
        InitializeComponent();
        cmbClassType.ItemsSource = Enum.GetValues(typeof(ClassType));
        cmbClassType.SelectedValue = CurrentValue;
    }

}

The Xaml part of the UserControl

<Grid>
    <ComboBox x:Name="cmbClassType" SelectedValue="{Binding Path=CurrentValue}"/>
</Grid>

Please check if it is working at your end. I have not added any extra code checking for thread safety and all.

EDIT

In my solution I do get my Class Property notification when the CurrentValue changes.

Below is my sample MainWindow Code.

public partial class MainWindow : Window, INotifyPropertyChanged
{
    public MainWindow()
    {
        InitializeComponent();
        DataContext = this;
        Task.Run(() =>
            {
                Thread.Sleep(1000);
                Dispatcher.InvokeAsync(() =>
                    {
                        customCombobox.CurrentValue = ClassType.Type3;//Updating the UserControl DP
                    });
                Thread.Sleep(2000);
                this.CurrentValue = ClassType.Type2;//Updating my local Property
            });
    }

    private ClassType _currentValue;
    public ClassType CurrentValue
    {
        get { return _currentValue; }
        set
        {
            _currentValue = value;
            Debug.WriteLine("Value Changed to " + value.ToString());
            RaisePropertyChanged("CurrentValue");
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
    void RaisePropertyChanged(string propName)
    {
        var pc = PropertyChanged;
        if (pc != null)
            pc(this, new PropertyChangedEventArgs(propName));
    }
}

And my MainWindow.xaml

<Window x:Class="WpfApplication.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:WpfApplication"
    Title="MainWindow" Height="250" Width="525">
<local:ClassSelector x:Name="customCombobox" Height="25" CurrentValue="{Binding CurrentValue}"/>
</Window>
Sandesh
  • 2,966
  • 1
  • 20
  • 34
  • Thanks alot, this is superstrange: if I set the Datacontext to the Grid, it is working, if I set it to the Window itself, it doesn't. As said, I need to learn more about the Datacontext and why such stuff is happening. – Matthias Müller Aug 16 '14 at 16:27
  • You are welcome :). Sometimes WPF becomes difficult while some times it is a cake walk. – Sandesh Aug 16 '14 at 16:33
  • Do you know why the Datacontext is behaving like this, but just for my Usercontrol and not for the other controls? – Matthias Müller Aug 16 '14 at 17:44