How to use command bindings in user controls in wpf?

前端 未结 2 573
一个人的身影
一个人的身影 2021-02-04 16:13

In MainWindow the commandbinding works fine. In UserControl1 it doesnt work. Note the datacontext is set correctly as is evidenced by the content of the button which is the res

相关标签:
2条回答
  • 2021-02-04 16:23

    Here I am AGAIN almost two years after I posted this. I forgot about this little feature of WPF and sure enough it bit me again.

    The answer marked above is partially correct but contains other content that is distracting and/or incorrect. For clarity I will highlight what the problem is and what the solution is. I'm doing this more for my benefit than yours because I'm sure I'll be back here in about sixteen months.

    Here is the problem. Don't do this. Your bindings will all continue to work except for your routed commands:

    <UserControl x:Class="CommandBindingTest.UserControl1"
         // snip
         d:DesignHeight="300" d:DesignWidth="300" x:Name="root">
    
        <Grid DataContext="{Binding ElementName=root}" >
            <Button Content="{Binding ButtonContent}" Command="{Binding ClickHereCommand}" Height="25" Width="90">
            </Button>
        </Grid>
    

    The solution is use relative source in setting the data context as follows:

    <Grid DataContext="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type UserControl}}}" >
        <Button Content="{Binding ButtonContent}" Command="{Binding ClickHereCommand}" Height="25" Width="90">
        </Button>
    </Grid>
    

    The only answer to the problem I asked about is the one above (there may in fact be other answers but they are not discussed thus far in this question). Specifically: Setting "DataContext = this" in the usercontrol is NOT a solution and will in fact break bindings in the control that hosts the user control. Also, only properties that are the targets of bindings must be dependency properties. That suggestion is incorrect .

    0 讨论(0)
  • 2021-02-04 16:35

    It's the best solution:

     <Grid DataContext="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type UserControl}}}" >
            <Button Content="{Binding ButtonContent}" Command="{Binding ClickHereCommand}" Height="25" Width="90"></Button>
     </Grid>
    

    Other solutions:

    You forgot set DataContext to UserControl1.

      public UserControl1()
            {
                InitializeComponent();
                ClickHereCommand = new RoutedCommand();
                CommandBindings.Add(new CommandBinding(ClickHereCommand, ClickHereExecuted));
                ButtonContent = "Click Here";
                this.DataContext = this;
            }
    

    And after this you must delete in UserControl1 DataContext in Grid.

    This:

    <Grid DataContext="{Binding ElementName=root}" >
        <Button Content="{Binding ButtonContent}" Command="{Binding ClickHereCommand}" Height="25" Width="90"></Button>
    </Grid>
    

    you must change to this:

    <Grid>
            <Button Content="{Binding ButtonContent}" Command="{Binding ClickHereCommand}" Height="25" Width="90"></Button>
    </Grid>
    

    Solution without set DataContext in UserControl:

    You must change ButtonContent and ClickHereCommand to DependencyProperty.

            public string ButtonContent
            {
                get { return (string)GetValue(ButtonContentProperty); }
                set { SetValue(ButtonContentProperty, value); }
            }
    
            public static readonly DependencyProperty ButtonContentProperty =
                DependencyProperty.Register("ButtonContent", typeof(string), typeof(UserControl1), new UIPropertyMetadata(string.Empty));
    
            public RoutedCommand ClickHereCommand
            {
                get { return (RoutedCommand)GetValue(ClickHereCommandProperty); }
                set { SetValue(ClickHereCommandProperty, value); }
            }
    
            public static readonly DependencyProperty ClickHereCommandProperty =
                DependencyProperty.Register("ClickHereCommand", typeof(RoutedCommand), typeof(UserControl1), new UIPropertyMetadata(null));
    

    And in ctor of UserControl1:

     public UserControl1()
        {
            InitializeComponent();
    
            ClickHereCommand = new RoutedCommand();
            CommandBindings.Add(new CommandBinding(ClickHereCommand, ClickHereExecuted));            
            ButtonContent = "Click Here";
            //this.DataContext = this;
        }
    
    0 讨论(0)
提交回复
热议问题