【问题标题】:WPF Bind to class member in code behindWPF 绑定到代码后面的类成员
【发布时间】:2011-01-22 22:37:07
【问题描述】:

很简单的问题,但似乎无法在这里找到完整的答案...

我需要将 xaml 中的数据绑定到代码隐藏中类成员的属性。

<Window x:Class="Main">
    <customcontrol Name="View" IsChecked="{Binding ElementName=RecordProp, Path=IsViewChecked}" />
...

后面的代码如下:

class Main 
{    
    ...
    private Record _record;
    public Record RecordProp
    {
      get { return _record; }
    }
    ...
}


class Record
{
  public bool IsViewChecked
  {
    get; set;
  }
}

我现在得到的东西不起作用,我做错了什么?

【问题讨论】:

    标签: c# wpf code-behind data-binding


    【解决方案1】:

    数据绑定不适用于私有字段。它适用于公共财产。尝试公开公开值 _record 并改为绑定到该值。

    参考 - http://msdn.microsoft.com/en-us/library/ms743643.aspx

    【讨论】:

    • 公共属性没有影响。
    • @user258651 我认为您还需要更新绑定上下文,以便主窗口将其默认返回到主类。不过,我已经有一段时间没有看了。
    【解决方案2】:

    Path 需要一个 Source 来反对(Source、DataContext、RelativeSource、ElementName)。 ElementName 只能用于引用在 XAML 中通过其 x:Name 声明的元素。试试这个,而不是指向你的窗口作为源:

    IsChecked="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}, Path=RecordProp.IsViewChecked}"
    

    【讨论】:

      【解决方案3】:

      我在这里看到的是你的窗口的类名是Main,你已经向它添加了一个RecordProp 属性,并且你现在正试图绑定到IsChecked 属性名为 RecordProp 的元素。我认为您对名称的工作方式有些困惑。

      x:Name 属性添加到 XAML 元素会在窗口类中使用该名称创建一个字段。这允许您在代码中引用命名元素,并且可能让您认为绑定可以做同样的事情。

      但这不是绑定找到命名元素的方式。 x:Name 属性 also 采用 XAML 元素创建的对象,并在窗口的名称范围内以该名称注册它。 (参见MSDN's article on XAML namescopes.)这就是绑定用来解析元素名称的方法。由于您从未将对象添加到名称范围,因此无法在绑定上设置 ElementName 属性。

      您可以做几件事。如果你真的想绑定到窗口的某个属性,你可以给窗口一个名字,然后使用属性路径绑定到该属性:

      <Window x:Name="MainWindow" x:Class="Main">
      ...
         <customcontrol Name="View" IsChecked="
                       {Binding ElementName=MainWindow, 
                        Path=RecordProp.IsViewChecked}" />
      

      更简单的是在构造函数中设置数据上下文:

      DataContext = this;
      

      完成此操作后,您可以像这样绑定到RecordProp 属性(以及窗口的任何其他属性):

      <customControl Name="View" IsChecked={Binding RecordProp.IsChecked}/>
      

      当然,如果您需要将窗口的数据上下文设置为其他内容,这将不起作用。

      另一种可能性是像这样实现属性:

      public Record RecordProp 
      {
        get { return (Record)Resources["RecordProp"]; }
        set { Resources["RecordProp"] = value; }
      }
      

      您可以使用(例如)Binding {DynamicResource RecordProp}, Path=IsChecked" 绑定到此。因为它是一个动态资源,如果窗口外部的东西设置了窗口的RecordProp 属性,它的绑定将会刷新——如果你只是将RecordProp 设置为一个属性就不会发生这种情况(除非你实现更改通知)。

      【讨论】:

      • 请注意,DataContext 不应在 Window 构造函数中设置,而应在 Loaded 事件处理程序中设置。当我在 Loaded 事件中填充 ObservableCollection 时,在构造函数中设置它对我不起作用。
      • 无需从代码中设置WindowsDataContext,您只需将其添加到Windows 的XAML:DataContext="{Binding RelativeSource={RelativeSource Self}}
      【解决方案4】:

      我相信我有一个比目前所说的更简单的答案。只需将其添加到 XAML 中的窗口声明(第一个标记):

      x:Name="this"
      

      然后你可以像这样进行数据绑定:

      <customcontrol Name="View" IsChecked="{Binding ElementName=this, Path=RecordProp.IsViewChecked}" />
      

      我检查了 C# 是否抱怨已经有一个“this”,但它没有,我猜是因为它们都引用了完全相同的对象。

      这是我遇到同样问题时使用的解决方案,我发现它使用起来非常直观。

      【讨论】:

      • 有理由不这样做吗?我尝试了其他解决方案但没有成功。这是我能够使用我的菜鸟 C# 技能使其工作的唯一方法。
      • 如果您投反对票,请评论为什么您认为这是一个糟糕的解决方案。
      猜你喜欢
      • 2018-11-24
      • 1970-01-01
      • 1970-01-01
      • 2019-10-01
      • 1970-01-01
      • 2015-11-07
      • 2018-12-08
      • 2018-05-08
      • 1970-01-01
      相关资源
      最近更新 更多