wpf - 来自 UserControl 的 WPF 绑定 MainWindow 控件,PropertyChanged 未触发
问题描述
我是 WPF 的新手,遇到了关于绑定的问题。我有一个使用绑定来更改视觉属性的MainWindow
with a 。Rectangle
XAML 代码如下:
<Rectangle Height="72" Canvas.Left="1011" RadiusY="6" RadiusX="6" StrokeThickness="2" Width="82" Canvas.Top="8">
<Rectangle.Style>
<Style TargetType="Rectangle">
<Style.Triggers>
<DataTrigger Binding="{Binding BddState}" Value="True">
<Setter Property="Fill">
<Setter.Value>
<ImageBrush ImageSource="Pictures/BDD_on.png" Stretch="Uniform" />
</Setter.Value>
</Setter>
</DataTrigger>
<DataTrigger Binding="{Binding BddState}" Value="False">
<Setter Property="Fill">
<Setter.Value>
<ImageBrush ImageSource="Pictures/Bdd_off.png" Stretch="Uniform" />
</Setter.Value>
</Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</Rectangle.Style>
</Rectangle>
我创建了一个视图模型类来管理绑定:
public class ViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(String propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
handler(this, new PropertyChangedEventArgs(propertyName));
}
private Boolean _bddstate;
public Boolean BddState
{
get { return _bddstate; }
set
{
_bddstate = value;
OnPropertyChanged("BddState");
}
}
}
绑定在 MainWindow 中运行良好,使用:
private ViewModel _viewModel = new ViewModel();
public MainWindow()
{
InitializeComponent();
this.DataContext = _viewModel;
_viewModel.BddState = true;
}
在 内部MainWindow
,我使用 aStackPanel
来加载不同UserControl
的(MainWindow
充当标题)。我担心的是来自UserControl
; MainWindow
BddState 值会相应更改,但UI上没有任何反映。同时,我可以看到视图模型的处理程序总是null
.
我究竟做错了什么?
预先感谢您的支持。
更新:这是用户控件的代码:
<Grid Background="#FFECECEC" Height="706" VerticalAlignment="Top">
<Label x:Name="label" Content="HOME" HorizontalAlignment="Left" Margin="525,8,0,0" VerticalAlignment="Top" FontWeight="Bold" Foreground="{DynamicResource gray_2}" FontSize="20"/>
<Label x:Name="label_Copy" Content="General Info" HorizontalAlignment="Left" Margin="441,34,0,0" VerticalAlignment="Top" Foreground="{DynamicResource gray_2}" FontSize="18"/>
<Button x:Name="button" Content="Button" HorizontalAlignment="Left" Margin="441,214,0,0" VerticalAlignment="Top" Width="107" Height="36" Click="button_Click"/>
</Grid>
对于后面的代码,它只是以下内容:
public partial class Home : UserControl
{
public Home()
{
InitializeComponent();
}
private void button_Click(object sender, RoutedEventArgs e)
{
ViewModel _vm = new ViewModel();
_vm.BddState = true;
}
}
当我单击 Home UC 的按钮时,ViewModel 的处理程序为 null,并且绑定在 MainWindow 矩形上无效
这里有一些更新跟随安迪的样本(它可以帮助),通过投射主窗口数据上下文它可以工作:
MainWindowViewModel viewModel = App.Current.MainWindow.DataContext as MainWindowViewModel;
if (viewModel != null)
{
viewModel.BddState = true;
}
解决方案
我将您的标记修改为:
<Canvas Name="MyCanvas" >
<Rectangle Height="72" RadiusY="6" RadiusX="6" StrokeThickness="2" Width="82" Canvas.Top="8">
<Rectangle.Style>
<Style TargetType="Rectangle">
<Style.Triggers>
<DataTrigger Binding="{Binding BddState}" Value="True">
<Setter Property="Fill" Value="Green"/>
</DataTrigger>
<DataTrigger Binding="{Binding BddState}" Value="False">
<Setter Property="Fill" Value="Yellow"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Rectangle.Style>
</Rectangle>
</Canvas>
它不依赖任何图像,也没有 Canvas.Left。
我得到一个绿色矩形。
您什么都看不到的可能原因包括:
您的窗口比 1011px 窄,并且 Canvas.Left="1011" 表示您的矩形不在窗口内。
您的图像路径不起作用。
均匀拉伸会产生问题,其中包含任何图片的矩形部分不在屏幕上。
然后我进一步修改它,通过视图模型中的私有支持字段将 bddstate 设置为 true。添加了一个将 ischecked 绑定到 bddstate 的切换按钮。这成功地在黄色和绿色之间切换。
这是一个工作版本涉及一个用户控件。我从测试样本中的 BaseViewModel 继承了 MainWindowViewModel。
主窗口:
<Window.DataContext>
<local:MainWindowViewModel/>
</Window.DataContext>
<Grid>
<Canvas Name="MyCanvas" >
<Rectangle Height="72" RadiusY="6" RadiusX="6" StrokeThickness="2" Width="82" Canvas.Top="8">
<Rectangle.Style>
<Style TargetType="Rectangle">
<Setter Property="Fill" Value="Green"/>
<Style.Triggers>
<DataTrigger Binding="{Binding BddState}" Value="False">
<Setter Property="Fill" Value="Yellow"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Rectangle.Style>
</Rectangle>
</Canvas>
<local:UserControl1 Height="30" Width="100"/>
</Grid>
视图模型:
public class MainWindowViewModel : BaseViewModel
{
private Boolean _bddstate = true;
public Boolean BddState
{
get { return _bddstate; }
set
{
_bddstate = value;
RaisePropertyChanged("BddState");
}
}
用户控件1
<ToggleButton Width="100" Height="30" Content="Toggle" IsChecked="{Binding BddState, Mode=TwoWay}"/>
基础视图模型
public class BaseViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected void RaisePropertyChanged([CallerMemberName] String propertyName = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
后面没有代码。
这仍然有效。
推荐阅读
- python - 使用 python 和 pandas 读取雅虎数据时出错
- python - 读入文件并仅打印每行的最后一个单词,如果这些单词是 8 个字符或更长并且不包含 #、@ 或 : 符号
- oracle - PLSQL 获取所有表数据
- c# - 按下回车键时 Visual Studio 执行关闭
- java - 实时改变一个变量android的值
- linux - 如何使用 xdg-open 将应用程序置于最前面
- python - tweepy.Cursor 在特定时间之前打印推文的属性是什么?
- php - $this->validate 导致“加载响应数据失败”
- performance - 多节点上的 h2o 和 hadoop 上的 h2o 有什么区别?
- java - JEP和JCP有什么区别或关系