Привязка объектов, определенных в коде программной части



у меня есть некоторый объект, который создается в коде позади, например, 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" правильно? но это в конечном итоге показывает ничего.

660   10  

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

сделайте свое свойство "windowname" DependencyProperty и сохраните его таким же.

в коде позади, установите 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

    Ничего не найдено.