2017-06-13 49 views
1

我只是試圖創建一個用戶控件使用WPF/Caliburn UserControl內的綁定,但我有麻煩,正確綁定嵌套UserControl。WPF和Caliburn不綁定嵌套用戶控件

基本佈局是一個ShellViewModel:Conductor,並且在ShellView中有一個ContentControl,它由加載UserControl(PageViewModel)的ShellViewModel.ActivateItem方法填充,並且在PageView UserControl中有一個嵌套的UserControl,名爲「 SimpleControl」。

當頁面加載時它會起作用(它在嵌套UserControl中顯示「Initial Text Value」字符串),但它不會綁定到PageView上的PropertyChanged事件(並且在測試時從不更新其值按鈕被按下)。父用戶控件(PageView)中的標籤按預期正確綁定/更新。

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我正在嘗試使用,但我創建了這個簡單的示例來嘗試找出問題。

回答

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文章!