C# 将可见性属性绑定到变量

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/14692461/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-10 12:41:47  来源:igfitidea点击:

Bind visibility property to a variable

c#wpfxamlbordervisibility

提问by 7zawel

I have a Borderwith Labelinside a Window,

我有一个BorderLabelWindow

<Border x:Name="Border1" BorderBrush="Black" BorderThickness="1" HorizontalAlignment="Left" Height="21" Margin="229,164,0,0" VerticalAlignment="Top" Width="90" Opacity="0.5">
    <Grid>
        <Label Content="test"/>
    </Grid>
</Border>

I have also a Variable:

我也有一个Variable

public bool vis = false;

How could I bind the visvariable with border Visibilityproperty?

我怎么能用vis边框Visibility属性绑定变量?

采纳答案by Mare Infinitus

If you already have your bool variable in a viewmodel, you have two things to do:

如果您已经在视图模型中拥有 bool 变量,那么您需要做两件事:

  1. make it a property, like:

    public bool vis { get; set; }

  1. 使它成为一个属性,例如:

    public bool vis { get; set; }

And you need a visibility converter for your property then:

并且您需要为您的财产设置一个可见性转换器:

It is described here:

它在这里描述:

http://social.msdn.microsoft.com/Forums/en/wpf/thread/3c0bef93-9daf-462f-b5da-b830cdee23d9

http://social.msdn.microsoft.com/Forums/en/wpf/thread/3c0bef93-9daf-462f-b5da-b830cdee23d9

The example assumes that you have a viewmodel and use Binding

该示例假设您有一个视图模型并使用 Binding

Here is some demo code that I made from your snippet:

这是我根据您的代码段制作的一些演示代码:

ViewModel:

视图模型:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;

namespace StackOverflowWpf2
{
    public class BorderViewModel : INotifyPropertyChanged
    {
        private bool borderVisible = false;

        public bool BorderVisible 
        {
            get
            {
                return borderVisible;
            }

            set
            {
                borderVisible = value;
                NotifyPropertyChanged("BorderVisible");
            }
        }

        private void NotifyPropertyChanged(string info)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(info));
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;
    }
}

XAML:

XAML:

<Window x:Class="StackOverflowWpf2.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Window.Resources>
        <BooleanToVisibilityConverter x:Key="BoolToVisConverter" />
    </Window.Resources>
    <Grid>
        <Border x:Name="Border1" BorderBrush="Black" BorderThickness="1" HorizontalAlignment="Left" Height="21" Margin="229,164,0,0" VerticalAlignment="Top" Width="90" Opacity="0.5"
                Visibility="{Binding Path=BorderVisible, Converter={StaticResource BoolToVisConverter} }" >
            <Grid>
                <Label Content="test"/>
            </Grid>
        </Border>
        <Button Content="Button" Height="23" HorizontalAlignment="Left" Margin="381,35,0,0" Name="button1" VerticalAlignment="Top" Width="75" Click="button1_Click" 
                />
    </Grid>
</Window>

Some Codebehind quick testcode: (actually is MainWindow.xaml.cs)

一些 Codebehind 快速测试代码:(实际上是 MainWindow.xaml.cs)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace StackOverflowWpf2
{
    /// <summary>
    /// Interaktionslogik für MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public BorderViewModel ViewModel { get; set; }

        public MainWindow()
        {
            InitializeComponent();

            ViewModel = new BorderViewModel();

            this.DataContext = ViewModel;

        }

        private void button1_Click(object sender, RoutedEventArgs e)
        {
            var vis = (this.DataContext as BorderViewModel).BorderVisible;

            (this.DataContext as BorderViewModel).BorderVisible = !vis;

        }
    }
}

回答by Cédric Bignon

You can't bind field. You can only bind public properties or dependency properties.

你不能绑定字段。您只能绑定公共属性或依赖属性。

Using public property (you have to implement INotifyPropertyChangedinterface to have property->binding):

使用公共属性(您必须实现INotifyPropertyChanged接口才能拥有属性->绑定):

public partial class MainWindow : Window, INotifyPropertyChanged
{
    private bool vis;
    public bool Vis
    {
        get { return vis; }
        set
        {
            if (vis != value)
            {
                vis = value;
                OnPropertyChanged("Vis");  // To notify when the property is changed
            }
        }
    }

    public MainWindow()
    {
        InitializeComponent();

        Vis = true;
        // DataContext explains WPF in which object WPF has to check the binding path. Here Vis is in "this" then:
        DataContext = this;          
    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        Vis = !Vis;  // Test Code
    }

    #region INotifyPropertyChanged implementation
    // Basically, the UI thread subscribes to this event and update the binding if the received Property Name correspond to the Binding Path element
    public event PropertyChangedEventHandler PropertyChanged;
    protected virtual void OnPropertyChanged(string propertyName)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
            handler(this, new PropertyChangedEventArgs(propertyName));
    }
    #endregion
}

The XAML code is:

XAML 代码是:

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/netfx/2009/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:WpfApplication1"
        xmlns:System="clr-namespace:System;assembly=mscorlib"
        Title="MainWindow2" Height="233" Width="392">

    <Window.Resources>
        <!-- You can implement your own BooleanToVisibilityConverter but there is one already implemented. So the next line creates an instance of the BooleanToVisibilityConverter that you will be able to reference with the specified key -->
        <BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/>
    </Window.Resources>

    <Grid>
        <Button Content="Click on the button to test" Click="Button_Click" Margin="0,0,0,165" />
        <Border x:Name="Border1" BorderBrush="Black" BorderThickness="1" HorizontalAlignment="Left" Height="21" Margin="229,164,0,0" VerticalAlignment="Top" Width="90" Opacity="0.5"
                Visibility="{Binding Vis, Converter={StaticResource BooleanToVisibilityConverter}}">
            <!-- The previous line define the binding : the path = Vis and the Converter to use -->
            <Grid>
                <Label Content="test"/>
            </Grid>
        </Border>
    </Grid>
</Window>

回答by TrueEddie

First you will need to make vis a Property:

首先,您需要创建 vis 属性:

private bool _vis;

public bool Vis
{
    get{return _vis;}
    set
    {
        if(_vis != value)
        {
            _vis = value;
        }
    }
}

Then you will need a ValueConverter.

那么您将需要一个 ValueConverter。

[ValueConversion(typeof(bool), typeof(Visibility))]
    public class VisibilityConverter : IValueConverter
    {
        public const string Invert = "Invert";

        #region IValueConverter Members

        public object Convert(object value, Type targetType, object parameter,
            System.Globalization.CultureInfo culture)
        {
            if (targetType != typeof(Visibility))
                throw new InvalidOperationException("The target must be a Visibility.");

            bool? bValue = (bool?)value;

            if (parameter != null && parameter as string == Invert)
                bValue = !bValue;

            return bValue.HasValue && bValue.Value ? Visibility.Visible : Visibility.Collapsed;
        }

        public object ConvertBack(object value, Type targetType, object parameter,
            System.Globalization.CultureInfo culture)
        {
            throw new NotSupportedException();
        }
        #endregion
    }

You will need to create an instance of the converter like so in your resources:

您需要在资源中像这样创建转换器的实例:

<UserControl.Resources>
    <cvt:VisibilityConverter x:Key="VisibilityConverter" />
</UserControl.Resources>

Then you can bind your border like so:

然后你可以像这样绑定你的边框:

<Border x:Name="Border1" Visibility="{Binding vis, Converter={StaticResource VisibilityConverter}}>
    <Grid>
        <Label Content="test"/>
    </Grid>
</Border>

回答by Ladislav Ondris

You don't need to make any converter.

您不需要制作任何转换器。

Add a binding to a Visibility property for the border:

将绑定添加到边框的可见性属性:

<Border x:Name="Border1" Visibility="{Binding Visibility}"    BorderBrush="Black" BorderThickness="1" HorizontalAlignment="Left" Height="21" Margin="229,164,0,0" VerticalAlignment="Top" Width="90" Opacity="0.5">
    <Grid>
        <Label Content="test"/>
    </Grid>
</Border>

And then create the property Visibility in a viewmodel like this:

然后在像这样的视图模型中创建属性 Visibility:

private Visibility visibility;
public Visibility Visibility
    {
        get
        {
            return visibility;
        }
        set
        {
            visibility = value;

            OnPropertyChanged("Visibility");
        }
    }

So, now you can set Visible or Hidden to your Visibility property as follow:

因此,现在您可以将 Visible 或 Hidden 设置为您的 Visibility 属性,如下所示:

Visibility = Visibility.Visible;
// or
Visibility = Visibility.Hidden;

But remember, Visibility enum is located in System.Windows namespace, so your viewmodel has to contain using System.Windows;.

但请记住,可见性枚举位于 System.Windows 命名空间中,因此您的视图模型必须包含using System.Windows;.

回答by A. Morel

Another solution is to use Trigger Style:

另一种解决方案是使用触发器样式:

<Border x:Name="Border1" BorderBrush="Black" BorderThickness="1" HorizontalAlignment="Left" Height="21" Margin="229,164,0,0" VerticalAlignment="Top" Width="90" Opacity="0.5">
    <Border.Style>
        <Style TargetType="Border">
            <Setter Property="Visibility" Value="Visible"/>
            <Style.Triggers>
                <DataTrigger Binding="{Binding Path=vis, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged }" Value="False">
                    <Setter Property="Visibility" Value="Hidden"/>
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </Border.Style>
    <Grid>
        <Label Content="test"/>
    </Grid>
</Border>

In the model class:

在模型类中:

public class ModelClass: INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    private void NotifyPropertyChanged(string name)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
    }

    private bool _vis;
    public bool vis
    {
        get => _vis;
        set
        {
            _vis = value;
            NotifyPropertyChanged("vis");
        }
    }
}

Don't forget to bind DataContext with your model !

不要忘记将 DataContext 与您的模型绑定!

DataContext = new ModelClass();