可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I have a Border
with Label
inside a Window
,
<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
:
public bool vis = false;
How could I bind the vis
variable with border Visibility
property?
回答1:
If you already have your bool variable in a viewmodel, you have two things to do:
make it a property, like:
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
The example assumes that you have a viewmodel and use 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:
<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)
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;
}
}
}
回答2:
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:
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:
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;
.
回答3:
You can't bind field. You can only bind public properties or dependency properties.
Using public property (you have to implement INotifyPropertyChanged
interface to have property->binding):
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:
<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>
回答4:
First you will need to make vis a Property:
private bool _vis;
public bool Vis
{
get{return _vis;}
set
{
if(_vis != value)
{
_vis = value;
}
}
}
Then you will need a 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>