Настройка Datacontext - PullRequest
       34

Настройка Datacontext

0 голосов
/ 15 марта 2020

Хорошо, сейчас я попытаюсь объяснить мои упражнения. Это мой PageOverzicht.xaml, и этот код работает. Это дает мне раскрывающийся список с цветами цветов (синий, оранжевый, белый, ...). Теперь текст данных жестко закодирован, чтобы найти цветы белого цвета. Цель: установить datacontext с помощью кода позади, чтобы следующим шагом было использование свойства selectionchanged для выбора цветов с выбранным цветом.

Так что теперь мне нужно сначала установить datacontext, чтобы он не был жестко запрограммирован на белый цвет. . Listbox состоит из xml узлов, названий растений, имеющих белый цвет, с использованием метода Page_Loaded из PageOverzicht.

<Page x:Class="Planten_BIS.PageOverzicht"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
      xmlns:local="clr-namespace:Planten_BIS"
      mc:Ignorable="d"
      d:DesignHeight="450" d:DesignWidth="800"
      Title="PageOverzicht">

    <Page.Resources>
        <XmlDataProvider x:Key="CatalogDataSource" XPath="catalog" Source="data/catalogus.xml"></XmlDataProvider>
        <DataTemplate x:Key="listItemTemplate">
            <StackPanel Orientation="Horizontal">
                <TextBlock Name="ImageName" Visibility="Collapsed" Text="{Binding XPath=botanical, StringFormat=images/{0}.jpg}" />

                <Border BorderBrush="white" BorderThickness="2" CornerRadius="10" Background="{StaticResource AchtergrondKleur}">
                    <Rectangle Width="100" Height="100" RadiusX="10" RadiusY="10">
                        <Rectangle.Fill>
                            <ImageBrush ImageSource="{Binding Text, ElementName=ImageName}" />
                        </Rectangle.Fill>
                    </Rectangle>
                </Border>
                <StackPanel Orientation="Vertical" Margin="10" VerticalAlignment="Center">
                    <ListBoxItem Content="{Binding XPath=common}"/>
                    <ListBoxItem Content="{Binding XPath=price}"/>
                </StackPanel>
            </StackPanel>
        </DataTemplate>
    </Page.Resources>
    <Grid>
        <ListBox Name="ListboxFlowers" Background="Transparent" Foreground="white" DataContext="{Binding Source={StaticResource CatalogDataSource}, XPath=color[@name\=\'White\']/plant}" ItemsSource="{Binding}" ItemTemplate="{StaticResource listItemTemplate}"></ListBox>
    </Grid>
</Page>

небольшая часть из xml, откуда поступают данные:

<?xml version="1.0" encoding="ISO8859-1" ?>
<catalog>
  <color name="White">
    <plant>
      <common>Jacob's Ladder</common>
      <botanical>Polemonium caeruleum i</botanical>
      <zone>Annual</zone>
      <light>Shade</light>
      <price>$9.26</price>
      <availability>022199</availability>
      <color>white</color>
      <description>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</description>
    </plant>

Главное окно с рамкой в ​​PageOverzicht:

<Window x:Class="Planten_BIS.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:scm="clr-namespace:System.ComponentModel;assembly=WindowsBase"
        xmlns:local="clr-namespace:Planten_BIS"
        mc:Ignorable="d"
        Title="Plant Catalog" Height="600" Width="800">
    <Window.Resources>
        <Style x:Key="buttonStyle" TargetType="Button">
            <Setter Property="Background" Value="{StaticResource ToolBarKleur}" />
            <Setter Property="BorderBrush" Value="{StaticResource RandKleur}" />
            <Setter Property="Foreground" Value="{StaticResource LetterKleur}" />
            <Setter Property="Height" Value="30" />
            <Setter Property="Margin" Value="6" />
        </Style>
        <Style x:Key="comboStyle" TargetType="ComboBox">
            <Setter Property="Background" Value="{StaticResource ToolBarKleur}" />
            <Setter Property="BorderBrush" Value="{StaticResource RandKleur}" />
            <Setter Property="Foreground" Value="{StaticResource LetterKleur}" />
            <Setter Property="Width" Value="100" />
            <Setter Property="Height" Value="30" />
            <Setter Property="Margin" Value="6" />
        </Style>
        <XmlDataProvider x:Key="CatalogDataSource" XPath="catalog" Source="data/catalogus.xml"></XmlDataProvider>
        <CollectionViewSource x:Key="cvsColors" Source="{StaticResource CatalogDataSource}">
            <CollectionViewSource.SortDescriptions>
                <scm:SortDescription PropertyName="color" />
            </CollectionViewSource.SortDescriptions>
        </CollectionViewSource>
        <DataTemplate x:Key="comboItemTemplate">
            <Label Content="{Binding XPath=@name}"/>
        </DataTemplate>

    </Window.Resources>
    <DockPanel LastChildFill="True">
        <ToolBar Background="{StaticResource ToolBarKleur}" DockPanel.Dock="Top">
            <Button Style="{StaticResource buttonStyle}" Content="Backward"></Button>
            <Button Style="{StaticResource buttonStyle}" Content="Forward"></Button>
            <ComboBox Style="{StaticResource comboStyle}" SelectedIndex="0"  ItemsSource="{Binding Source={StaticResource CatalogDataSource}, XPath=color}" ItemTemplate="{StaticResource comboItemTemplate}"></ComboBox>
        </ToolBar>
        <Frame Source="PageOverzicht.xaml" Name="frame" NavigationUIVisibility="Hidden">
            <Frame.Background>
                <ImageBrush ImageSource="assets/background.jpg" Stretch="UniformToFill"/>
            </Frame.Background>
        </Frame>
    </DockPanel>
</Window>

1 Ответ

0 голосов
/ 15 марта 2020

Обработка источника данных должна быть перенесена в элемент управления, который является общим родителем ComboBox и Frame, в этом случае я выбрал MainWindow.

Вы должны добавить необходимые DependecyProperty определения к MainWindow, которые можно использовать для привязки данных для ComboBox.ItemsSource, ComboBox.SelectedItem и Frame.DataContext.

Для Обработка XML Я заменил XMLDataProvider на источник данных XElement, который позволяет LINQ To XML для удобной фильтрации или обхода дерева объектов XML в C#.

Теперь ComboBox привязывает к коллекции XElement элементов, представляющих XML color узлов. Выбранный элемент ComboBox представляет собой один элемент XML color. Узлы-потомки plant из color используются для установки Frame.DataContext, который наследуется в Page.DataContext. ListBox в Page теперь связывает его ItemsSource непосредственно с DataContext, который является свойством MainWindow.PlantsOfSelectedColor. В качестве альтернативы, например, если вам нужно установить Page.DataContext на что-то другое, вы можете позволить Binding пройти по визуальному дереву, чтобы найти MainWindow.PlantsOfSelectedColor, используя RelativeSource FindAncestor для Binding.RelativeSource из ListBox.ItemsSource.

MainWindow.xaml.cs

public partial class MainWindow : Window
{
  public static readonly DependencyProperty PlantColorNodesProperty = DependencyProperty.Register(
    "PlantColorNodes",
    typeof(IEnumerable<XElement>),
    typeof(MainWindow),
    new PropertyMetadata(default(IEnumerable<XElement>)));

  public IEnumerable<XElement> PlantColorNodes
  {
    get => (IEnumerable<XElement>) GetValue(MainWindow.PlantColorNodesProperty);
    set => SetValue(MainWindow.PlantColorNodesProperty, value);
  }

  public static readonly DependencyProperty SelectedPlantColorNodeProperty = DependencyProperty.Register(
    "SelectedPlantColorNode",
    typeof(XElement),
    typeof(MainWindow),
    new PropertyMetadata(default(XElement), OnSelectedPlantColorNodeChanged));

  public XElement SelectedPlantColorNode
  {
    get => (XElement) GetValue(MainWindow.SelectedPlantColorNodeProperty);
    set => SetValue(MainWindow.SelectedPlantColorNodeProperty, value);
  }

  public static readonly DependencyProperty PlantsOfSelectedColorProperty = DependencyProperty.Register(
    "PlantsOfSelectedColor",
    typeof(IEnumerable<XElement>),
    typeof(MainWindow),
    new PropertyMetadata(default(IEnumerable<XElement>)));

  public IEnumerable<XElement> PlantsOfSelectedColor
  {
    get => (IEnumerable<XElement>) GetValue(MainWindow.PlantsOfSelectedColorProperty);
    set => SetValue(MainWindow.PlantsOfSelectedColorProperty, value);
  }

  public MainWindow()
  {
    InitializeComponent();

    // Open XML an collect all 'color' nodes
    this.PlantColorNodes = XElement.Load("data/catalogus.xml").Elements("color");
  }

  private static void OnSelectedPlantColorNodeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
  {
    var colorNode = e.NewValue as XElement;

    // Get the 'plant' child nodes of the selected 'color' node
    (d as MainWindow).PlantsOfSelectedColor = colorNode.Elements();
  }
}

MainWindow.xaml

<Window>
  <DockPanel LastChildFill="True">
    <ComboBox ItemsSource="{Binding RelativeSource={RelativeSource AncestorType=MainWindow}, Path=PlantColorNodes}" 
              SelectedItem="{Binding RelativeSource={RelativeSource AncestorType=MainWindow}, Path=SelectedPlantColorNode}">
      <ComboBox.ItemTemplate>
        <DataTemplate>
          <TextBlock Text="{Binding Attribute[name].Value}" />
        </DataTemplate>
      </ComboBox.ItemTemplate>
    <ComboBox>
    <Frame DatContext="{Binding RelativeSource={RelativeSource AncestorType=MainWindow}, Path=PlantsOfSelectedColor}"
           Source="PageOverzicht.xaml" />
    </DockPanel>
</Window>

PageOverzicht.xaml

<Page>
  <ListBox ItemsSource="{Binding}">
    <ListBox.ItemTemplate>
      <DataTemplate  >
        <StackPanel Orientation="Horizontal">
          <TextBlock Text="{Binding Element[botanical].Value}" />
          <TextBlock Text="{Binding Element[common].Value}"/>
          <TextBlock Text="{Binding Element[price].Value}"/>          
        </StackPanel>
      </DataTemplate>
    </ListBox.ItemTemplate>
  </ListBox>
</Page>
...