我对 WPF 数据绑定有点陌生,所以请耐心等待。我想要的行为是在 UserControl 中绑定一个 MenuItem 并使用它来折叠 MainWindow 中的框架。我正在使用和 booltoVisibility 转换器来帮助进行类型转换。当我运行代码时,框架不会折叠。在输出窗口中,我收到错误“无法将目标中的值保存回源...系统参数异常:“True”不是 Property CollapseFrame 的有效值”。我认为这可能与我构建依赖属性的方式有关,但我无法弄清楚。
主窗口.xaml
<Window x:Class="TestBooleanToVisibilityConverter.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:TestBooleanToVisibilityConverter"
xmlns:local1="clr-namespace:WpfApp1"
Title="MainWindow"
SizeToContent="WidthAndHeight"
DataContext="{Binding RelativeSource={RelativeSource Self}}">
<Grid Margin="30">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.Resources>
<local:BoolToVisibleOrHidden x:Key="BoolToVisConverter" Collapse="True" Reverse="True" />
</Grid.Resources>
<Frame
Grid.Column="0"
Grid.Row="0"
MinWidth= "200"
MinHeight= "20"
BorderBrush="Gray"
BorderThickness="3"
Visibility="{Binding FrameIsVisible, Converter={StaticResource BoolToVisConverter}}" >
</Frame>
<Grid Grid.Row="1">
<local1:Menu
CollapseFrame="{Binding FrameIsVisible, Converter={StaticResource BoolToVisConverter}}" >
</local1:Menu>
</Grid>
</Grid>
主窗口.xaml.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
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;
using WpfApp1;
namespace TestBooleanToVisibilityConverter
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
FrameIsVisible = false;
}
public bool FrameIsVisible { get; set; }
}
}
菜单.xaml
<UserControl x:Class="WpfApp1.Menu"
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:WpfApp1"
x:Name="myUserControl"
mc:Ignorable="d">
<Menu >
<MenuItem Header="_File">
<MenuItem x:Name="HideFrame" Header="Hide Frame" IsCheckable="True" IsChecked="{Binding ElementName=myUserControl, Path=CollapseFrame}" />
</MenuItem>
</Menu>
</UserControl>
菜单.xaml.cs
using System.Windows;
using System.Windows.Controls;
namespace WpfApp1
{
/// <summary>
/// Interaction logic for Menu.xaml
/// </summary>
public partial class Menu : UserControl
{
public Menu()
{
InitializeComponent();
}
public static readonly DependencyProperty CollapseFrameProperty =
DependencyProperty.Register("CollapseFrame",
typeof(Visibility),
typeof(Menu),
new FrameworkPropertyMetadata(Visibility.Visible));
public Visibility CollapseFrame
{
get { return (Visibility)GetValue(CollapseFrameProperty); }
set { SetValue(CollapseFrameProperty, value); }
}
}
}
BooleanToVisibleOrHidden.cs
using System;
using System.Windows.Data;
using System.Windows;
namespace TestBooleanToVisibilityConverter {
class BoolToVisibleOrHidden : IValueConverter
{
#region Constructors
public BoolToVisibleOrHidden() { }
#endregion
#region Properties
public bool Collapse { get; set; }
public bool Reverse { get; set; }
#endregion
#region IValueConverter Members
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
bool bValue = (bool)value;
if (bValue != Reverse)
{
return Visibility.Visible;
}
else
{
if (Collapse)
return Visibility.Collapsed;
else
return Visibility.Hidden;
}
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
Visibility visibility = (Visibility)value;
if (visibility == Visibility.Visible)
return !Reverse;
else
return Reverse;
}
#endregion
}
}
你需要一个转换器,它把来自一个Visibility
到Boolean
:
public class VisibleOrHiddenToBool : IValueConverter
{
#region Properties
public bool Collapse { get; set; }
public bool Reverse { get; set; }
#endregion
#region IValueConverter Members
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
Visibility visibility = (Visibility)value;
if (visibility == Visibility.Visible)
return !Reverse;
else
return Reverse;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
bool bValue = (bool)value;
if (bValue != Reverse)
{
return Visibility.Visible;
}
else
{
if (Collapse)
return Visibility.Collapsed;
else
return Visibility.Hidden;
}
}
#endregion
}
菜单.xaml:
<Grid>
<Grid.Resources>
<local:VisibleOrHiddenToBool x:Key="converter" />
</Grid.Resources>
<Menu >
<MenuItem Header="_File">
<MenuItem x:Name="HideFrame" Header="Hide Frame" IsCheckable="True"
IsChecked="{Binding ElementName=myUserControl, Path=CollapseFrame, Converter={StaticResource converter}}" />
</MenuItem>
</Menu>
</Grid>
然后,您应该将绑定到FrameIsVisible
窗口中的属性设置为TwoWay
:
<local:Menu x:Name="menu" CollapseFrame="{Binding FrameIsVisible, Converter={StaticResource BoolToVisConverter}, Mode=TwoWay}" />
最后,您还需要实现该INotifyPropertyChanged
接口并PropertyChanged
在窗口中引发通知:
public partial class MainWindow : Window, INotifyPropertyChanged
{
public MainWindow()
{
InitializeComponent();
}
private bool _frameIsVisible;
public bool FrameIsVisible
{
get { return _frameIsVisible; }
set { _frameIsVisible = value; OnPropertyChanged(); }
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged([CallerMemberName] String propertyName = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句