代码之家  ›  专栏  ›  技术社区  ›  wondra

DataTemplate的绑定为目标提供了不正确的/unset/null值

  •  0
  • wondra  · 技术社区  · 6 年前

    我想传播 DataContext 从动态创建的 DataTemplate 在一个 ContentControl 比如下面一个:

    var myFactory = new FrameworkElementFactory(controlTypeToDisplay);//= typeof(MyControl)
    var dctxBinding = new Binding
    {
        Path = new PropertyPath("DataContext.Dctx"),
        Mode = BindingMode.OneWayToSource,
        RelativeSource = new RelativeSource(RelativeSourceMode.FindAncestor, typeof(ContentControl), 1)
    };
    myFactory.SetBinding(FrameworkElement.DataContextProperty, dctxBinding);
    
    return new DataTemplate() { VisualTree = myFactory };
    

    然而,这种约束的结果是 null 即使DataContext是在 MyControl 的构造函数。MyControl的DataContext肯定不会再设置为null,构造函数是在 Dctx .我怎样才能把装订好 我的控制 的DataContext和 Dctx 属性总是同步的吗?


    问题的完整示例(如果工作正常,应显示两个“FooBar”文本块):

    //MyControl.xaml
    <Grid>
        <TextBlock Text="{Binding}"/>
    </Grid>
    //MyControl.xaml.cs
    public MyControl()
    {
        InitializeComponent();
        DataContext = "FooBar";
        this.DataContextChanged += MyControl_DataContextChanged;
    }
    
    private void MyControl_DataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
    {
        MessageBox.Show("An unexpected change");
    }
    
    //MainWindow.xaml
    <StackPanel>
        <ContentControl ContentTemplate="{Binding DataTemplate}"/>
        <TextBlock Text="{Binding Dctx, TargetNullValue='&lt;null&gt;'}" />
    </StackPanel>
    
    //MainWindow.xaml.cs
    public partial class MainWindow : Window, INotifyPropertyChanged
    {
        private Type controlTypeToDisplay = typeof(MyControl);
        public DataTemplate DataTemplate
        { get {/*see first listing*/ } }
    
        private object _dctx;
        public object Dctx
        {
            get { return _dctx; }
            set { _dctx = value; RaisePropertyChanged(); }
        }
    
        public MainWindow()
        {
            InitializeComponent();
            this.DataContext = this;
        }
    
        public event PropertyChangedEventHandler PropertyChanged;
        public void RaisePropertyChanged([CallerMemberName]string caller = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(caller));
        }
    }
    
    1 回复  |  直到 6 年前
        1
  •  0
  •   mm8    6 年前

    这个 DataContext 中的根元素的 ContentTemplate 一个 ContentControl 是吗 内容控制 是的 Content .绑好绳子 所容纳之物 财产归你所有 数据上下文 :

    <ContentControl Content="{Binding Dctx}" ContentTemplate="{Binding DataTemplate}"/>
    

    您还必须设置 数据上下文 关于 内容控制 自身(或父窗口)的某个位置,并向 DataTemplate :

    public partial class MainWindow : Window, INotifyPropertyChanged
    {
        public DataTemplate DataTemplate
        {
            get {
                var myFactory = new FrameworkElementFactory(typeof(TextBlock));
                myFactory.SetBinding(TextBlock.TextProperty, new Binding(".")); //bind to the DataContext
                return new DataTemplate() { VisualTree = myFactory };
            }
        }
    
        private object _dctx = new object(); //set the Dxtc property somewhere
        public object Dctx
        {
            get { return _dctx; }
            set { _dctx = value; RaisePropertyChanged(); }
        }
    
        public MainWindow()
        {
            InitializeComponent();
            DataContext = this;
        }
    
        public event PropertyChangedEventHandler PropertyChanged;
        public void RaisePropertyChanged([CallerMemberName]string caller = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(caller));
        }
    
    }