-1

How binding user control dependecy property? I want ToolTip dependency property IsEnabled to bind from UserControl dependency property IsShowToolTip. I try RelativeSource, but this can't find source.

In UserControl i have:

        public bool IsShowToolTip
        {
            get { return (bool)GetValue(IsShowToolTipProperty); }
            set { SetValue(IsShowToolTipProperty, value); }
        }

        public static readonly DependencyProperty IsShowToolTipProperty =
            DependencyProperty.Register("IsShowToolTip", typeof(bool), typeof(SideMenuView), new PropertyMetadata(false));

In xaml:

<UserControl>
    <ItemsControl ItemsSource="{Binding Items}"
        ScrollViewer.VerticalScrollBarVisibility="Disabled"
        ScrollViewer.HorizontalScrollBarVisibility="Disabled">
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <StackPanel Margin="0,0,0,12">
                    <RadioButton Content="{Binding MenuName}"
                                 GroupName="MainMenuButton"
                                 Command="{Binding ChangeViewCommand}">
                        <RadioButton .ToolTip>
                            <ToolTip Content="{Binding MenuName}" Placement="Right" HorizontalOffset="8"
                                     IsEnabled="{Binding IsShowToolTip, ?}">
                            </ToolTip>
                        <RadioButton.ToolTip>
                    <RadioButton >
                    <ListBox ItemsSource="{Binding SubItems}"
                             ScrollViewer.VerticalScrollBarVisibility="Disabled"
                             ScrollViewer.HorizontalScrollBarVisibility="Disabled"
                             VerticalAlignment="Stretch" HorizontalAlignment="Stretch"/>
                </StackPanel>
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl>
</UserControl>
EldHasp
  • 6,079
  • 2
  • 9
  • 24

2 Answers2

0

Is there any way to make it work?

A bit of voodoo magic... :)

using System.Windows;
using System.Windows.Controls;

namespace Core2022.SO.JarosławPietras
{
    /// <summary>
    /// Логика взаимодействия для SideMenuView.xaml
    /// </summary>
    public partial class SideMenuView : UserControl
    {
        public SideMenuView()
        {
            InitializeComponent();
        }

        public bool IsShowToolTip
        {
            get { return (bool)GetValue(IsShowToolTipProperty); }
            set { SetValue(IsShowToolTipProperty, value); }
        }

        public static readonly DependencyProperty IsShowToolTipProperty =
            DependencyProperty.Register("IsShowToolTip", typeof(bool), typeof(SideMenuView), new PropertyMetadata(false));
    }

    public class SideMenuViewProxy : Freezable
    {
        public SideMenuView? SideMenuView
        {
            get { return (SideMenuView?)GetValue(SideMenuViewProperty); }
            set { SetValue(SideMenuViewProperty, value); }
        }

        // Using a DependencyProperty as the backing store for SideMenuView.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty SideMenuViewProperty =
            DependencyProperty.Register(nameof(SideMenuView), typeof(SideMenuView), typeof(SideMenuViewProxy), new PropertyMetadata(null));


        protected override Freezable CreateInstanceCore()
        {
            throw new System.NotImplementedException();
        }
    }
}
<UserControl x:Class="Core2022.SO.JarosławPietras.SideMenuView"
             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:Core2022.SO.JarosławPietras"
             mc:Ignorable="d" 
             d:DesignHeight="450" d:DesignWidth="800">
    <UserControl.Resources>
        <local:SideMenuViewProxy
            x:Key="proxy"
            SideMenuView="{Binding Mode=OneWay, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:SideMenuView}}}"/>
    </UserControl.Resources>
    <Grid Background="AliceBlue">
        <Grid.ToolTip>
            <ToolTip IsEnabled="{Binding SideMenuView.IsShowToolTip, Source={StaticResource proxy}}" >
                <StackPanel>
                    <Button Content="Some Button"/>
                    <TextBlock Text="{Binding IsEnabled, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ToolTip}}}"/>
                </StackPanel>
            </ToolTip>
        </Grid.ToolTip>
        <CheckBox Content="on/off ToolTip"
                  IsChecked="{Binding IsShowToolTip, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:SideMenuView}}}"
                  VerticalAlignment="Top" HorizontalAlignment="Left"/>
    </Grid>
</UserControl>

P.S. This is one of the solutions. In addition to using StaticResource, you can also pass values through the DataContext. But it is usually occupied by the ViewModel. You can also make a proxy not entirely for the object, but only for the necessary properties.

Second Example

using System.Windows;
using System.Windows.Controls;

namespace Core2022.SO.JarosławPietras
{
    /// <summary>
    /// Логика взаимодействия для SideMenuView1.xaml
    /// </summary>
    public partial class SideMenuView1 : UserControl
    {
        public SideMenuView1()
        {
            InitializeComponent();
        }
    }

    public class MyProxy : Freezable
    {
        public bool IsToolTipEnabled
        {
            get { return (bool)GetValue(IsToolTipEnabledProperty); }
            set { SetValue(IsToolTipEnabledProperty, value); }
        }

        // Using a DependencyProperty as the backing store for SideMenuView.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty IsToolTipEnabledProperty =
            DependencyProperty.Register(nameof(IsToolTipEnabled), typeof(bool), typeof(MyProxy), new PropertyMetadata(true));


        protected override Freezable CreateInstanceCore()
        {
            throw new System.NotImplementedException();
        }
    }

}
<UserControl x:Class="Core2022.SO.JarosławPietras.SideMenuView1"
             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:Core2022.SO.JarosławPietras"
             mc:Ignorable="d" 
             d:DesignHeight="450" d:DesignWidth="800">
    <UserControl.Resources>
        <local:MyProxy x:Key="proxy"/>
    </UserControl.Resources>
    <Grid Background="AliceBlue">
        <Grid.ToolTip>
            <ToolTip IsEnabled="{Binding IsToolTipEnabled, Source={StaticResource proxy}}" >
                <StackPanel>
                    <Button Content="Some Button"/>
                    <TextBlock Text="{Binding IsEnabled, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ToolTip}}}"/>
                </StackPanel>
            </ToolTip>
        </Grid.ToolTip>
        <CheckBox Content="on/off ToolTip"
                  IsChecked="{Binding IsToolTipEnabled, Source={StaticResource proxy}}"
                  VerticalAlignment="Center" HorizontalAlignment="Center"/>
    </Grid>
</UserControl>

Full Example

Unfortunately, this method doesn't work in my example. Cannot see anything outside of the binding ItemSource.

Unfortunately, it is not possible to infer from your code what is causing your problem.

Here is a complete example demonstrating that everything works correctly.

using System.Windows;
using System.Windows.Controls;

namespace Core2022.SO.JarosławPietras
{
    public partial class SideMenuViewFull : UserControl
    {
        public SideMenuViewFull()
        {
            InitializeComponent();
        }

        public bool IsShowToolTip
        {
            get { return (bool)GetValue(IsShowToolTipProperty); }
            set { SetValue(IsShowToolTipProperty, value); }
        }

        public static readonly DependencyProperty IsShowToolTipProperty =
            DependencyProperty.Register("IsShowToolTip", typeof(bool), typeof(SideMenuViewFull), new PropertyMetadata(false));
    }

    public class SideMenuViewModel
    {
        public string[] Items { get; set; } =
        {
            "first",
            "second" ,
            "third" ,
            "fourth" ,
            "fifth" ,
            "sixth" ,
            "seventh" ,
            "eighth" ,
            "ninth" ,
            "tenth" ,
            "eleventh" ,
            "twelfth"
        };
    }
}
<UserControl x:Class="Core2022.SO.JarosławPietras.SideMenuViewFull"
             x:Name="PART_Main"
             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:Core2022.SO.JarosławPietras"
             mc:Ignorable="d" 
             d:DesignHeight="450" d:DesignWidth="800">
    <d:UserControl.DataContext>
        <local:SideMenuViewModel/>
    </d:UserControl.DataContext>
    <UserControl.Resources>
        <local:MyProxy x:Key="proxy"
                       IsToolTipEnabled="{Binding IsShowToolTip, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:SideMenuViewFull}}}"/>
    </UserControl.Resources>
    <ItemsControl ItemsSource="{Binding Items}"
        ScrollViewer.VerticalScrollBarVisibility="Disabled"
        ScrollViewer.HorizontalScrollBarVisibility="Disabled">
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <StackPanel Orientation="Horizontal" Margin="0,0,0,12">
                    <RadioButton Content="{Binding}" Width="100"
                                 GroupName="MainMenuButton">
                        <RadioButton.ToolTip>
                            <ToolTip Placement="Right" HorizontalOffset="8"
                                      IsEnabled="{Binding IsToolTipEnabled, Source={StaticResource proxy}}">
                                <StackPanel>
                                    <Button Content="{Binding}"/>
                                    <TextBlock Text="{Binding IsEnabled, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ToolTip}}}"/>
                                </StackPanel>
                            </ToolTip>
                        </RadioButton.ToolTip>
                    </RadioButton>
                    <TextBlock Text="{Binding IsToolTipEnabled, Source={StaticResource proxy}}"/>
                </StackPanel>
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl>
</UserControl>

XAML Window:

<Window x:Class="Core2022.SO.JarosławPietras.SideMenuViewFullWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:Core2022.SO.JarosławPietras"
        mc:Ignorable="d"
        Title="SideMenuViewFullWindow" Height="450" Width="800">
    <Window.DataContext>
        <local:SideMenuViewModel/>
    </Window.DataContext>
    <UniformGrid Columns="2">
        <CheckBox x:Name="checkBox" Content="Is Show ToolTip"/>
        <local:SideMenuViewFull IsShowToolTip="{Binding IsChecked, ElementName=checkBox}"/>
    </UniformGrid>
</Window>

Clicking the CheckBox in the Window changes the ToolTip.IsEnabled to the DataTemplate. Therefore, the button in the ToolTip is disabled.

EldHasp
  • 6,079
  • 2
  • 9
  • 24
  • Unfortunately, this method doesn't work in my example. Cannot see anything outside of the binding ItemSource. – Jarosław Pietras Sep 17 '22 at 16:29
  • @JarosławPietras, I've updated my answer with a more complete implementation. Check out this add-on. – EldHasp Sep 18 '22 at 06:07
  • I checked your solution and it works fine, but with me code something is wrong and IsShowToolTip changes the value, but IsToolTipEnabled doesn't change, it has the same value all the time. – Jarosław Pietras Sep 19 '22 at 11:35
  • Without seeing the full code, I can't tell where the error is. If you upload your solution to GitHub, I will try to look at it and find the cause of the problem. – EldHasp Sep 19 '22 at 14:52
0

You could simply bind the ToolTipService.IsEnabled attached property of the RadioButton to your dependency property like this:

<DataTemplate>
    <StackPanel Margin="0,0,0,12">
        <RadioButton Content="{Binding MenuName}"
                     GroupName="MainMenuButton"
                     Command="{Binding ChangeViewCommand}"
                     ToolTipService.IsEnabled="{Binding IsShowToolTip, 
                        RelativeSource={RelativeSource AncestorType=UserControl}}">
            <RadioButton.ToolTip>
                <ToolTip Content="{Binding MenuName}" Placement="Right" HorizontalOffset="8" />
            </RadioButton.ToolTip>
        </RadioButton>
    </StackPanel>
</DataTemplate>
mm8
  • 163,881
  • 10
  • 57
  • 88
  • It's not showing at all, Content property is probably not set, null value. :( – Jarosław Pietras Sep 16 '22 at 16:24
  • So now your question is how to bind the `Content` property or what? – mm8 Sep 19 '22 at 13:36
  • This does work if `IsShowToolTip` is a property of the `UserControl`. The toopltip should display the content of the `RadioButton` if this property is set to `true`. – mm8 Sep 19 '22 at 13:39