【问题标题】:How to achieve DataBinding of a code behind element?如何实现元素背后代码的DataBinding?
【发布时间】:2012-03-16 15:02:02
【问题描述】:

我有以下场景:我正在创建一个纸牌游戏,作为其中的一部分,我想创建一个 UserControl 以使界面编程更容易和更好。我正在创建以下用户控件:

.cs

public partial class ChimeraUserControl : UserControl
{   
    private ChimeraViewModel Chimera { get; set; }

    public ChimeraUserControl(Chimera chimera)
    {
        this.Chimera = new ChimeraViewModel(chimera);
        InitializeComponent();
    }
}

我希望能够做两件事:当使用这个用户控件时,能够通过绑定发送一个Chimera,并且,使所有的文本和其他元素都绑定到这个Chimera .我搜索了很多,但没有找到任何让我满意的东西。

你们觉得呢?

我已经尝试阅读的内容:

http://dev-for-fun.blogspot.com/2008/06/wpf-example-create-usercontrol-and.html

Binding from View-Model to View-Model of a child User Control in Silverlight? 2 sources - 1 target

还有很多其他页面,但似乎没有一个足够直截了当,并且通过破解其代码我没有找到问题的解决方案。

【问题讨论】:

  • 从我得到的支持中,我想这是一个真正的问题,即缺乏绑定文档。
  • 在您尝试执行所需操作的位置添加 xaml 或代码。它会更准确地显示问题。
  • 后面的代码在这里。稍后我将添加一段 XAML,尽管这不是 IMO 必需的,因为我在那里什么都做不了。

标签: wpf data-binding user-controls custom-controls


【解决方案1】:

我可以建议从你的任务中我能理解的任何事情开始。

  1. 您应该将此设置为自定义控件而不是 UserControl。

    查看以下链接以获取帮助 -

    Control Authoring Overview

    http://www.codeproject.com/Articles/49802/Create-a-WPF-Custom-Control-Part-2

  2. 使Chimera 成为DependencyProperty 以支持Binding(如您添加的SO 链接和上述文章中所述)。

【讨论】:

    【解决方案2】:

    首先,将Chimera 设为Dependency Property,以便它可以参与绑定系统

    public static readonly DependencyProperty ChimeraProperty = 
        DependencyProperty.Register("Chimera ", typeof(ChimeraViewModel), 
        typeof(ChimeraUserControl), new FrameworkPropertyMetadata(null));
    
    public ChimeraViewModel Chimera 
    {
        get { return (ChimeraViewModel)GetValue(ChimeraProperty ); }
        set { SetValue(ChimeraProperty, value); }
    }
    

    其次,您可以通过RelativeSourceElementName 绑定来引用您的Chimeria 属性

    <UserControl x:Name="ChimeraViewRoot" ... >
    
        <StackPanel>
            <!-- ElementName Binding -->
            <TextBlock Text="{Binding ElementName=ChimeraViewRoot, Path=Chimeria.Name}" />
    
            <!-- RelativeSource Binding -->
            <TextBlock Text="{Binding RelativeSource={RelativeSource AncestorType={x:Type local:ChimeraView}}, Path=Chimeria.Name}" />
    
        </StackPanel>
    </UserControl>
    

    您也可以将UserControl 中控件的DataContext 设置为Chimera 属性,以使您的绑定语法更简洁

    <UserControl x:Name="ChimeraViewRoot" ... >
        <StackPanel DataContext="{Binding RelativeSource={RelativeSource AncestorType={x:Type local:ChimeraView}}, Path=Chimeria}" >
    
            <TextBlock Text="{Binding Name}" />
            <TextBlock Text="{Binding Description}" />
    
        </StackPanel>
    </UserControl>
    

    我通常不建议在UserControl 中定义UserControl.DataContext,因为该值应该从使用UserControl 的任何地方传入。当您试图弄清楚为什么特定的 UserControl 不能与预期的 DataContext 一起工作时,在 UserControl 中设置可能会导致混淆。


    就我个人而言,当我创建一个应该与特定UserControl 一起使用的ViewModel 时,我更喜欢在应用程序中设置一个DataTemplate,以便我的ViewModel 的所有实例都使用我的自定义@987654342 绘制@。这意味着我假设 UserControl.DataContext 将始终是特定的 ViewModel 类型

    <DataTemplate DataType="{x:Type local:ChimeriaViewModel}">
        <local:ChimeriaView /> <!-- DataContext will always be ChimeriaViewModel -->
    </DataTemplate>
    

    每当可视树遇到ChimeriaViewMmodel 类型的对象时,这将隐式使用ChimeriaView

    例如,下面将渲染一个填充有ChimeriaView对象的StackPanel

    <ItemsControl ItemsSource="{Binding MyListOfChimeriaViewModels}" />
    

    或者为了显示单个对象,我通常会使用 ContentControl 之类的东西

    <!-- Will get drawn using ChimeriaView due to DataTemplate defined above -->
    <ContentControl Content="{Binding MyChimeriaViewModelProperty}" />
    

    另外,通过知道ChimeriaViewDataContext 将成为ChimeriaViewModel 类型的对象,我将完全摆脱DependencyProperty

    <UserControl>
        <StackPanel>
            <!-- I know the DataContext is ChimeriaViewModel -->
            <TextBlock Text="{Binding Name}" />
            <TextBlock Text="{Binding Description}" />
    
        </StackPanel>
    </UserControl>
    

    【讨论】:

    • 非常感谢!现在这很简单!
    • 问题:我定义的是 DataTemplate 而不是 UserControl?
    • @Bruno 我根据需要使用DataTemplatesUserControls。如果在它自己的控件中对元素进行分组是有意义的,我将使用UserControl。如果它很简单,或者范围更小,我会使用DataTemplate。此外,将DataTemplate 放置在任何有意义的地方。如果它正在定义应用程序范围的模板,请将其放入Application.Resources。如果是用户控制模板,则放入UserControl.Resources
    猜你喜欢
    • 2012-10-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-16
    • 2014-05-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多