WPF Привязать к члену класса в коде
Довольно простой вопрос, но не может найти полного ответа здесь...
Мне нужно привязать databind в 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;
}
}
То, что у меня сейчас, не работает, что я делаю неправильно?
Ответы
Ответ 1
Путь нуждается в источнике, против которого идут (Source, DataContext, RelativeSource, ElementName). ElementName может использоваться только для обозначения элементов, объявленных в XAML, их x: Name. Попробуйте вместо этого указать на свое окно в качестве источника:
IsChecked="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}, Path=RecordProp.IsViewChecked}"
Ответ 2
То, что я вижу здесь, это то, что ваше имя класса окна 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"
. Поскольку это динамический ресурс, если что-то внешнее к окну устанавливает свойство window RecordProp
, привязки к нему будут обновляться - это то, чего не произойдет, если вы просто сделаете свойство RecordProp
(если вы не внесете изменения в уведомление об изменении).
Ответ 3
Я считаю, что у меня более простой ответ, чем те, которые были указаны до сих пор. Просто добавьте это в объявление окна (самый первый тег) в XAML:
x:Name="this"
Затем вы можете привязать данные следующим образом:
<customcontrol Name="View" IsChecked="{Binding ElementName=this, Path=RecordProp.IsViewChecked}" />
Я проверил, что С# жалуется, что уже есть "это", и это не так, я думаю, потому что они оба относятся к одному и тому же объекту.
Это решение, которое я использовал, когда столкнулся с той же проблемой, и нашел, что это очень интуитивно понятно.
Ответ 4
Связывание данных не будет работать против частных полей. Вместо этого это предназначалось для публичных объектов. Попробуйте публиковать значение _record
публично и привязать к нему.
Ссылка
- http://msdn.microsoft.com/en-us/library/ms743643.aspx