从UserControl WPF绑定MainWindow控件,未触发PropertyChanged

时间:2019-04-17 14:46:09

标签: wpf binding

我是WPF的新手,并且面临有关绑定的问题。 我有一个MainWindow和一个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内,我使用StackPanel来加载不同的UserControlMainWindow充当标题)。 我关心的是UserControl的绑定; BddState值会相应更改,但是MainWindow 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矩形无效

这里是安迪(Andy)示例之后的一些更新(可能会有所帮助) 通过强制转换mainwindow datacontext:

 MainWindowViewModel viewModel = App.Current.MainWindow.DataContext as MainWindowViewModel;
        if (viewModel != null)
        {
            viewModel.BddState = true;
        }

1 个答案:

答案 0 :(得分:1)

我将您的标记修改为:

    <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”表示您的矩形不在窗口内。

您的图像路径不起作用。

均匀拉伸会造成问​​题,矩形中没有图片的部分不在屏幕上。

然后我进一步修改了它,以最初通过viewmodel中的私有后备字段将bddstate设置为true。添加了一个ischecked绑定到bddstate的切换按钮。 可以成功在黄色和绿色之间切换。

这是一个涉及用户控件的有效版本。我已经从测试样本中的BaseViewModel继承了MainWindowViewModel。

MainWindow:

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

UserControl1

    <ToggleButton Width="100" Height="30" Content="Toggle" IsChecked="{Binding BddState, Mode=TwoWay}"/>

BaseViewModel

public  class BaseViewModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    protected void RaisePropertyChanged([CallerMemberName] String propertyName = "")
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

没有任何代码。

这仍然有效。