Visibility Binding using DependencyProperty

 ̄綄美尐妖づ 提交于 2020-01-23 17:32:04

问题


I've some simple code below that uses a ToggleButton.IsChecked property to set the Visibility of a TextBlock. It works fine. Since this doesn't quite fit in with my program's structure, I'm trying to bind the visibility of another TextBlock to a DependencyProperty of "this". It compiles fine, but it produces no effect. I'm doing something wrong, just not sure what.

XAML

<Window x:Class="ToggleButtonTest.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Width="200" Height="100">
<Window.Resources>
    <BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/>
</Window.Resources>
<StackPanel>
    <ToggleButton x:Name="toggleButton" Content="Toggle"
                  IsChecked="True" Checked="toggleButton_Checked"/>
    <TextBlock Text="Some Text"
               Visibility="{Binding IsChecked, 
               ElementName=toggleButton,
               Converter={StaticResource BooleanToVisibilityConverter}}"/>
    <TextBlock Text="More Text"
               Visibility="{Binding ShowMoreText, 
               ElementName=this, 
               Converter={StaticResource BooleanToVisibilityConverter}}"/>
</StackPanel>
</Window>

C#

using System.Windows;

namespace ToggleButtonTest
{
    public partial class MainWindow : Window
    {
        static MainWindow()
        {
            FrameworkPropertyMetadata meta = 
                new FrameworkPropertyMetadata(true,
                FrameworkPropertyMetadataOptions.BindsTwoWayByDefault);

            ShowMoreTextProperty = 
                DependencyProperty.Register("ShowMoreText", 
                typeof(bool), typeof(MainWindow), meta);
        }

        public MainWindow()
        {
            InitializeComponent();
        }

        public static readonly DependencyProperty ShowMoreTextProperty;
        public bool ShowMoreText
        {
            get
            {
                return (bool)GetValue(ShowMoreTextProperty);
            }
            set
            {
                SetValue(ShowMoreTextProperty, value);
            }
        }

        private void toggleButton_Checked(object sender, RoutedEventArgs e)
        {
            ShowMoreText = toggleButton.IsChecked.Value;
        }
    }
}

Edit:

Having had this answered, I want to post my working code...

XAML

<Window x:Class="ToggleButtonTest.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Width="200" Height="100"
    Name="thisWindow">
    <Window.Resources>
        <BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/>
    </Window.Resources>
    <StackPanel>
        <ToggleButton x:Name="toggleButton" 
                Content="Toggle"
                IsChecked="{Binding Path=ShowMoreText, ElementName=thisWindow}"/>
        <TextBlock Text="More Text"
                   Visibility="{Binding Path=ShowMoreText, 
                   ElementName=thisWindow,
                   Converter={StaticResource BooleanToVisibilityConverter}}"/>
    </StackPanel>
</Window>

C#

using System.Windows;

namespace ToggleButtonTest
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        public static readonly DependencyProperty ShowMoreTextProperty =
            DependencyProperty.Register("ShowMoreText", typeof(bool),
            typeof(MainWindow), new FrameworkPropertyMetadata(true,
                FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));

        public bool ShowMoreText
        {
            get
            {
                return (bool)GetValue(ShowMoreTextProperty);
            }
            set
            {
                SetValue(ShowMoreTextProperty, value);
            }
        }
    }
}

回答1:


ElementName must really be an element name. this doesn't fly. Fortunately, you do have an element of type MainWindow here with a ShowMoreText property: the root Window element.

Give the Window a name and use that as ElementName, as below:

<Window x:Class="ToggleButtonTest.MainWindow"
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
     Title="MainWindow" Width="200" Height="100"
     x:Name="thisWindow">
<Window.Resources>
     <BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/>
</Window.Resources>
<StackPanel>
     <ToggleButton x:Name="toggleButton" Content="Toggle"
                        IsChecked="True" Checked="toggleButton_Checked"/>
     <TextBlock Text="Some Text"
                    Visibility="{Binding IsChecked, 
                    ElementName=toggleButton,
                    Converter={StaticResource BooleanToVisibilityConverter}}"/>
     <TextBlock Text="More Text"
                    Visibility="{Binding ShowMoreText, 
                    ElementName=thisWindow, 
                    Converter={StaticResource BooleanToVisibilityConverter}}"/>
</StackPanel>
</Window>

Note that you can do the same using RelativeSource Self, but I prefer the method above.




回答2:


The way you have it set up currently won't ever set ShowMoreText to false. The Checked handler will only be called when the ToggleButton's IsChecked changes from false to true. To also go the other way you need a handler for Unchecked as well. The best way to handle this situation would be to instead set a Binding on the ToggleButton that will do both without any event handlers (using Jay's changes):

IsChecked="{Binding Path=ShowMoreText, ElementName=thisWindow}"



回答3:


Give your Window a name and set the ElementName to that name, instead of using "this".



来源:https://stackoverflow.com/questions/3560683/visibility-binding-using-dependencyproperty

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!