WPF和Caliburn不绑定嵌套的UserControl

时间:2017-06-13 05:18:48

标签: c# wpf xaml user-controls caliburn.micro

我只是尝试使用WPF / Caliburn在UserControl中为UserControl创建绑定,但是我无法正确绑定嵌套的UserControl。

基本布局是一个ShellViewModel:Conductor,在ShellView中有一个ContentControl,由加载UserControl(PageViewModel)的ShellViewModel.ActivateItem方法填充,而在PageView UserControl中有一个名为“SimpleControl”的嵌套UserControl ”

页面加载时绑定有效(它在嵌套的UserControl中显示“初始文本值”字符串),但它似乎没有绑定到PageView上的PropertyChanged事件(并且在测试按钮时从不更新其值按下)。父UserControl(PageView)中的Label按预期正确绑定/更新。

PageView.xaml:

<UserControl x:Class="CaliburnTest.Views.PageView"
             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:CaliburnTest.Views"
             xmlns:cal="http://www.caliburnproject.org"
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300">
    <StackPanel Background="Aqua">
        <Label Content="{Binding TextLabelTest, FallbackValue=DEFAULT}"></Label>
        <local:SimpleControl cal:Bind.Model="WPFCaliburnTemplate.Views.PageView" TextValue="{Binding TextLabelTest}"></local:SimpleControl>
        <Button Name="UpdateTextButton">Update Text</Button>
    </StackPanel>
</UserControl>

PageViewModel.cs:

using Caliburn.Micro;

namespace CaliburnTest.ViewModels
{
    public class PageViewModel : Screen
    {
        private string _textLabelTest;
        public string TextLabelTest
        {
            get { return _textLabelTest; }
            set
            {
                _textLabelTest = value;
                NotifyOfPropertyChange(() => TextLabelTest);
            }
        }

        public PageViewModel()
        {
            TextLabelTest = "Initial Text Value";
        }

        public void UpdateTextButton()
        {
            TextLabelTest = "Updated Text Value";
        }
    }
}

SimpleControl.xaml:

<UserControl x:Class="CaliburnTest.Views.SimpleControl"
             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:cal="clr-namespace:Caliburn.Micro;assembly=Caliburn.Micro.Platform.Core"
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300">
    <Border Margin="10" BorderThickness="1" BorderBrush="#FF9A9A9A">
        <StackPanel>
            <Label Name="TextLabel"></Label>
        </StackPanel>        
    </Border>
</UserControl>

最后是SimpleControl.xaml.cs:

using System.Windows;
using System.Windows.Controls;

namespace CaliburnTest.Views
{
    public partial class SimpleControl : UserControl
    {
        public SimpleControl()
        {
            InitializeComponent();
        }

        public static DependencyProperty TextValueProperty = DependencyProperty.Register("TextValue", typeof(string), typeof(SimpleControl),
            new FrameworkPropertyMetadata("", TextValueChangedCallBack));
        public string TextValue
        {
            get { return (string)GetValue(TextValueProperty); }
            set
            {
                SetValue(TextValueProperty, value);
                Refresh();
            }
        }

        protected static void TextValueChangedCallBack(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            (sender as SimpleControl).TextValue = (string)e.NewValue;
        }

        private void Refresh()
        {
            TextLabel.Content = TextValue;
        }
    }
}

我整天都在敲打这件事,无法弄清楚我做错了什么。我已经尝试了不同的DataContexts,RelativeSources以及我在SO和Google上可以找到的任何其他组合的所有组合,但我仍然很短。我有一个更复杂的自定义UserControl我正在尝试使用但我创建了这个简单的例子来试图找出问题。

1 个答案:

答案 0 :(得分:0)

我玩各种各样的组合,我相信我发现了一个似乎有用的结果,虽然我不完全确定原因:

首先,我改变了将“TextValue”依赖项属性绑定到:

的方式
    <local:SimpleControl TextValue="{Binding RelativeSource={RelativeSource FindAncestor, 
                AncestorType={x:Type UserControl}}, Path=DataContext.TextLabelTest}" />

但是,这仍然只适用于初始值,并且更新字符串时绑定未更新。最后,我必须像这样编辑SimpleControl.xaml.cs:

    protected static void TextValueChangedCallBack(DependencyObject sender, DependencyPropertyChangedEventArgs e)
    {
        // (sender as SimpleControl).TextValue = (string)e.NewValue;
        (sender as SimpleControl).Refresh();
    }

正如您所看到的,我注释掉设置SimpleControl.TextValue的行(并依次设置TextValueProperty DependencyProperty)并简单地调用SimpleControl.Refresh()方法来更新标签。我不确定为什么设置TextValueProperty会破坏DependencyProperty(即使它已在字符串更新时设置),但我想我需要了解一些MSDN文章!