0

I'm trying to bind passing the custom object of type "CommandButton_VModel" to an User control through a dependency property, but it seems the setter of this dp is never hit. I mean at the user control the dependency property is always null, could someone please advise-me on where am I failing?

Here's my code below:

UserControl XAML:

<UserControl x:Class="FireAntTempConfigurer.UserControls.CommandButton_UC"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:FireAntTempConfigurer.UserControls"
             xmlns:materialDesign="clr-namespace:MaterialDesignThemes.Wpf;assembly=MaterialDesignThemes.Wpf"
             mc:Ignorable="d" 
             TextElement.Foreground="{DynamicResource MaterialDesignPaper}"
             d:DesignHeight="60 " d:DesignWidth="60">
    <Grid>
        <Button Height="50" Padding="0,0,0,0" Margin="5" ToolTip="{Binding PlaceHolder}">
            <Button.Content>
                <materialDesign:PackIcon Kind="{Binding Icon}" Height="50" Width="50" />
            </Button.Content>
        </Button>
    </Grid>
</UserControl>

UserControl Code Behind

    public partial class CommandButton_UC : UserControl
    {

        public CommandButton_UC()
        {
            DataContext = CmdBtn;
            InitializeComponent();
        }

        public CommandButton_VModel CmdBtn
        {
            get { return (CommandButton_VModel)GetValue(CmdBtnProperty); }
            set { SetValue(CmdBtnProperty, value); }
        }

        public static readonly DependencyProperty CmdBtnProperty =
            DependencyProperty.Register("CmdBtn", typeof(CommandButton_VModel), typeof(CommandButton_UC), new PropertyMetadata(default(CommandButton_VModel)));
    }

MainWindow XAML:

            <StackPanel>
                <TextBlock>ToolBox:</TextBlock>
                <Separator></Separator>
                <StackPanel Orientation="Horizontal">
                    <cmdBtn:CommandButton_UC CmdBtn="{Binding MyProperty ,Mode=OneWayToSource}">
                    </cmdBtn:CommandButton_UC>
                </StackPanel>
            </StackPanel>

MainWindow Code

    public partial class MainWindow : Window
    {

        public CommandButton_VModel MyProperty { get; set; }

        public MainWindow()
        {
            MyProperty = new CommandButton_VModel { Icon = "Plus", PlaceHolder = "Add" };
            DataContext = MyProperty;
            InitializeComponent();
        }


    }

ViewModel

    public class CommandButton_VModel : INotifyPropertyChanged
    {
        public string Icon { get; set; }
        public string PlaceHolder { get; set; }

        public event PropertyChangedEventHandler PropertyChanged;

        public CommandButton_VModel()
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs("Icon"));
                PropertyChanged(this, new PropertyChangedEventArgs("PlaceHolder"));
            }
        }
    }

Thanks!

  • You must not explicitly set the UserControl's DataContext (e.g. to `this` or to some property value of the control or some private view model). If you do that, a Binding like `CmdBtn="{Binding MyProperty}"` won't work, because MyProperty is expected in the current DataContext, which should be inherited from the control's parent, e.g. the window. – Clemens Apr 10 '19 at 17:35
  • The MainWindow constructor however should set `DataContext = this;` because it owns `MyProperty`. – Clemens Apr 10 '19 at 17:36
  • And as explained in the answer to the original question, the Bindings in the UserControl's XAML should use RelativeSource, like `Kind="{Binding CmdBtn.Icon, RelativeSource={RelativeSource AncestorType=UserControl}}"` – Clemens Apr 10 '19 at 17:39
  • Alternatively, keep `Kind="{Binding Icon}"` but set the DataContext of the top level element in the UserControl: `` – Clemens Apr 10 '19 at 17:41
  • Finally, a better approach would be a UserControl that has no knowledge at all of a particular view model. Replace the `CmdBtn` property (and hence the dependency on a certain VM type) with two separate properties `Icon` and `PlaceHolder` that you individually bind to your view model by `` – Clemens Apr 10 '19 at 17:44
  • As a note, trying to fire the PropertyChanged event from the CommandButton_VModel constructor is pointless. The PropertyChanged event will always be null there, hence the code is useless. It should be removed. – Clemens Apr 10 '19 at 17:47
  • Thank you very much for your time Mr. Clemens, be sure I'll modify to that better approach you metioned on your comments. Regards – Rodrigo Tavernaro Queiroz Apr 10 '19 at 18:11

0 Answers0