WPF Привязка к члену класса в коде позади - PullRequest
30 голосов
/ 03 марта 2010

Довольно простой вопрос, но не могу найти здесь полного ответа ...

Мне нужно привязать данные в xaml к свойству члена класса в codebehind.

<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;
  }
}

То, что у меня сейчас, не работает, что я делаю не так?

Ответы [ 4 ]

30 голосов
/ 03 марта 2010

Здесь я вижу, что имя класса вашего окна Main, что вы добавили к нему свойство RecordProp, и что вы сейчас пытаетесь привязать к свойству IsChecked элемент с именем RecordProp. Я думаю, вы немного озадачены тем, как работают имена.

Добавление атрибута x:Name к элементу XAML создает поле в классе окна с этим именем. Это позволяет вам ссылаться на именованные элементы в вашем коде, и это, вероятно, привело вас к мысли, что привязка может делать то же самое.

Но привязка не находит именованные элементы. Атрибут x:Name также принимает объект, который создает элемент XAML, и регистрирует его под этим именем в области имен окна. (См. статью MSDN по именным областям XAML. ) Это то, на что смотрит привязка для разрешения имен элементов. Поскольку вы никогда не добавляете объект в область имен, установка свойства 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 (если вы не реализуете уведомление об изменении ).

27 голосов
/ 03 марта 2010

Для пути требуется источник, с которым нужно идти (источник, DataContext, RelativeSource, ElementName) ElementName может использоваться только для ссылки на элементы, объявленные в XAML их x: Name. Попробуйте вместо этого указать ваше окно в качестве источника:

IsChecked="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}, Path=RecordProp.IsViewChecked}"
7 голосов
/ 18 апреля 2011

Полагаю, у меня есть более простой ответ, чем те, которые были заявлены до сих пор. Просто добавьте это в объявление окна (самый первый тег) в XAML:

x:Name="this"

Тогда вы можете связать данные следующим образом:

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

Я проверил, жалуется ли C # на то, что уже есть «this», и это не так, я думаю, потому что они оба ссылаются на один и тот же объект.

Это решение, которое я использовал, когда столкнулся с той же проблемой, и нашел его очень интуитивным в использовании.

3 голосов
/ 03 марта 2010

Привязка данных не будет работать с закрытыми полями.Вместо этого он предназначен для публичной собственности.Попробуйте выставить значение _record публично и вместо этого привязать к нему.

Ссылка - http://msdn.microsoft.com/en-us/library/ms743643.aspx

...