繁体   English   中英

将可见性属性绑定到变量

[英]Bind visibility property to a variable

我在Window有一个带LabelBorder

<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>

我也有一个Variable

public bool vis = false;

如何将vis变量与 border Visibility属性绑定?

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

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

<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>

然后在您的 ViewModel 中创建 Visibility 属性:

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

            OnPropertyChanged("Visibility");
        }
    }

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

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

Visibility 枚举位于 System.Windows 命名空间中,因此您的 ViewModel 必须包含using System.Windows; .

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

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

    public bool vis { get; set; }

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

它在这里描述:

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

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

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

视图模型:

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:

<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>

一些 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;

        }
    }
}

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

使用公共属性(您必须实现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
}

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>

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

private bool _vis;

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

那么您将需要一个 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
    }

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

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

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

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

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

<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>

在模型类中:

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");
        }
    }
}

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

DataContext = new ModelClass();

使用 INotifyPropertyChanged 和 @Ladislav Ondris 的示例。 连同以下绑定 Visibility="{x:Bind Visibility, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" 对我有用。 没有使用 Visibility.Collapsed 和 Visbility.Visible 显示更新。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM