Подтвердить что ты не робот

Объекты привязки, определенные в кодировке

У меня есть некоторый объект, который создается в коде позади, например, XAML называется window.xaml и внутри window.xaml.cs

protected Dictionary<string, myClass> myDictionary;

Как связать этот объект с, например, с представлением списка, используя только разметки XAML?

Update:

(Это точно в моем тестовом коде):

<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" правильным? но он ничего не показывает.

4b9b3361

Ответ 1

Вы можете установить 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 свойства из любого элемента управления в окне.

Ответ 2

Там намного проще это сделать. Вы можете назначить имя своему окну или 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();
    }
}

Ответ 3

В то время как ответ Guy правильный (и, вероятно, подходит для 9 из 10 случаев), стоит отметить, что если вы пытаетесь сделать это из элемента управления, у которого уже установлен его DataContext, то вы сбросите его, когда вы установите DataContext для себя:

DataContext="{Binding RelativeSource={RelativeSource Self}}"

Это, конечно же, сломает существующие привязки.

Если это так, вы должны установить RelativeSource для элемента управления, который вы пытаетесь связать, а не его родителя.

то есть. для привязки к свойствам UserControl:

Binding Path=PropertyName, 
        RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}

Учитывая, насколько сложно в настоящее время увидеть, что происходит с привязкой данных, стоит иметь в виду это, даже если вы обнаружите, что в настоящее время работает настройка RelativeSource={RelativeSource Self}:)

Ответ 4

Немного больше разъяснений: Свойство без '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>

Ответ 5

Определите конвертер:

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

Ответ 6

Сделайте свой ресурс "windowname" зависимым свойством и сохраните оставшееся.

Ответ 7

В вашем коде позади установите окно DataContext в словарь. В вашем XAML вы можете написать:

<ListView ItemsSource="{Binding}" />

Это свяжет ListView со словарем.

Для более сложных сценариев это будет подмножество методов, лежащих в основе MVVM.

Ответ 8

Одним из способов было бы создание ObservableCollection (System.Collections.ObjectModel) и наличие в нем данных словаря. Затем вы сможете привязать ObservableCollection к вашему ListBox.

В вашем XAML у вас должно быть что-то вроде этого:

<ListBox ItemsSource="{Binding Path=Name_of_your_ObservableCollection" />

Ответ 9

У меня была такая же проблема, но моя была не потому, что я устанавливал локальную переменную... Я был в дочернем окне, и мне нужно было установить относительный DataContext, который я только что добавил в Window 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">

Ответ 10

Вы можете попробовать x: Справочный трюк

<Window ... x:Name="myWindow"><ListBox ItemsSource="{Binding Items, Source={x:Reference myWindow}}" /></Window>