Привязка объектов, определенных в коде программной части
у меня есть некоторый объект, который создается в коде позади, например, XAML называется window.xaml и внутри окна.код XAML.cs
protected Dictionary<string, myClass> myDictionary;
как я могу привязать этот объект, например, к списковому представлению, используя только разметки XAML?
обновление:
(это именно у меня в моем тестовом коде):
<Window x:Class="QuizBee.Host.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="{Binding windowname}" Height="300" Width="300"
DataContext="{Binding RelativeSource={RelativeSource Self}}">
<Grid>
</Grid>
</Window>
и в codebehind
public partial class Window1 : Window
{
public const string windowname = "ABCDEFG";
public Window1()
{
InitializeComponent();
}
}
предположим, что название должно стать "ABCDEFG" правильно? но это в конечном итоге показывает ничего.
10 ответов:
Вы можете установить DataContext для вашего элемента управления, формы и т. д. вот так:
DataContext="{Binding RelativeSource={RelativeSource Self}}"уточнение:
контекст данных, устанавливаемый на значение выше, должен быть выполнен в любом элементе, "владеющем" кодом позади - поэтому для окна вы должны установить его в объявлении окна.
у меня есть ваш пример работы с этим кодом:
<Window x:Class="MyClass" Title="{Binding windowname}" DataContext="{Binding RelativeSource={RelativeSource Self}}" Height="470" Width="626">набор DataContext на этом уровне затем наследуется любым элементом в окне (если только вы явно изменяете его для дочернего элемента), поэтому после установки DataContext для окна вы должны быть в состоянии просто сделать прямую привязку к CodeBehind свойства из любого элемента управления в окне.
есть гораздо более простой способ сделать это. Вы можете назначить имя своему окну или UserControl, а затем привязать по ElementName.
файл window1.xaml
<Window x:Class="QuizBee.Host.Window1" x:Name="Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> <ListView ItemsSource="{Binding ElementName=Window1, Path=myDictionary}" /> </Window>файл window1.код XAML.cs
public partial class Window1:Window { // the property must be public, and it must have a getter & setter public Dictionary<string, myClass> myDictionary { get; set; } public Window1() { // define the dictionary items in the constructor // do the defining BEFORE the InitializeComponent(); myDictionary = new Dictionary<string, myClass>() { {"item 1", new myClass(1)}, {"item 2", new myClass(2)}, {"item 3", new myClass(3)}, {"item 4", new myClass(4)}, {"item 5", new myClass(5)}, }; InitializeComponent(); } }
хотя ответ Гая верен (и, вероятно, подходит для 9 из 10 случаев), стоит отметить, что если вы пытаетесь сделать это из элемента управления, у которого уже есть свой DataContext, настроенный далее в стеке, вы сбросите это, когда вы установите DataContext обратно к себе:
DataContext="{Binding RelativeSource={RelativeSource Self}}"Это, конечно, затем разорвать существующие привязки.
Если это так, вы должны установить RelativeSource на контроль, который вы пытаетесь привязать, а не его родитель.
т. е. для привязки к свойствам UserControl:
Binding Path=PropertyName, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}учитывая, как трудно в настоящее время увидеть, что происходит с привязкой данных, стоит иметь это в виду, даже если вы найдете эту настройку
RelativeSource={RelativeSource Self}в настоящее время работает :)
еще немного уточнений:свойство без 'get', ' set ' не сможет быть привязано
я сталкиваюсь с делом так же, как случай Аскера. И я должен иметь следующие вещи для того, чтобы привязка работала правильно:
//(1) Declare a property with 'get','set' in code behind public partial class my_class:Window { public String My_Property { get; set; } ... //(2) Initialise the property in constructor of code behind public partial class my_class:Window { ... public my_class() { My_Property = "my-string-value"; InitializeComponent(); } //(3) Set data context in window xaml and specify a binding <Window ... DataContext="{Binding RelativeSource={RelativeSource Self}}"> <TextBlock Text="{Binding My_Property}"/> </Window>
определить конвертер:
public class RowIndexConverter : IValueConverter { public object Convert( object value, Type targetType, object parameter, CultureInfo culture ) { var row = (IDictionary<string, object>) value; var key = (string) parameter; return row.Keys.Contains( key ) ? row[ key ] : null; } public object ConvertBack( object value, Type targetType, object parameter, CultureInfo culture ) { throw new NotImplementedException( ); } }привязка к пользовательскому определению словаря. Есть много переопределений, которые я пропустил, но индексатор является важным, потому что он выдает событие изменения свойства при изменении значения. Это необходимо для привязки исходного кода к целевому.
public class BindableRow : INotifyPropertyChanged, IDictionary<string, object> { private Dictionary<string, object> _data = new Dictionary<string, object>( ); public object Dummy // Provides a dummy property for the column to bind to { get { return this; } set { var o = value; } } public object this[ string index ] { get { return _data[ index ]; } set { _data[ index ] = value; InvokePropertyChanged( new PropertyChangedEventArgs( "Dummy" ) ); // Trigger update } } }в свой .xaml-файл используйте этот конвертер. Первая ссылка на него:
<UserControl.Resources> <ViewModelHelpers:RowIndexConverter x:Key="RowIndexConverter"/> </UserControl.Resources>тогда, например, если в вашем словаре есть запись, где ключом является "имя", то чтобы привязать к нему: используйте
<TextBlock Text="{Binding Dummy, Converter={StaticResource RowIndexConverter}, ConverterParameter=Name}">
в коде позади, установите DataContext окна в словарь. В XAML, вы можете написать:
<ListView ItemsSource="{Binding}" />это свяжет ListView со словарем.
для более сложных сценариев, это будет подмножество методов за MVVM узор.
одним из способов было бы создать ObservableCollection (System.Коллекции.ObjectModel) и есть ваши данные словаря там. Затем вы должны быть в состоянии привязать ObservableCollection к вашему списку.
в вашем XAML вы должны иметь что-то вроде этого:
<ListBox ItemsSource="{Binding Path=Name_of_your_ObservableCollection" />
У меня была точно такая же проблема, но не потому, что я сидел в локальную переменную... Я был в дочернем окне, и мне нужно было установить относительный DataContext, который я только что добавил в окно XAML.
<Window x:Class="Log4Net_Viewer.LogItemWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" DataContext="{Binding RelativeSource={RelativeSource Self}}" Title="LogItemWindow" Height="397" Width="572">
вы можете попробовать X: ссылка трюк
<Window ... x:Name="myWindow"><ListBox ItemsSource="{Binding Items, Source={x:Reference myWindow}}" /></Window>
Comments