设置数据上下文

Setting Datacontext

好的,我现在要尝试解释一下我的练习.. 这是我的 PageOverzicht.xaml,此代码有效。它给了我一个下拉菜单,其中包含花朵的颜色(蓝色,橙色,白色,......)。现在数据上下文被硬编码以找到白色的花。 目标:通过隐藏代码设置数据上下文,以便下一步可以使用 selectionchanged 属性 到 select 带有 selected 颜色的花朵。

所以现在我需要先设置数据上下文,这样它就不会硬编码为白色.. 列表框包含 xml 个节点,白色植物的名称,使用来自 PageOverzicht 的 Page_Loaded 方法。

<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>.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>

应将数据源处理移至 ComboBoxFrame 的公共父控件,在本例中我选择了 MainWindow

您应该将所需的 DependecyProperty 定义添加到 MainWindow,可用于 ComboBox.ItemsSourceComboBox.SelectedItemFrame.DataContext 的数据绑定.

对于 XML 处理,我将 XMLDataProvider 替换为允许 LINQ To XML 的 XElement 数据源,以便轻松地过滤或遍历 XML C# 中的对象树。

现在 ComboBox 绑定到代表 XML color 个节点的 XElement 项的集合。所选 ComboBox 项是单个 XML color 元素。 color的后代plant个节点用于设置Frame.DataContext,继承给Page.DataContextPage 中的 ListBox 现在将其 ItemsSource 直接绑定到 DataContext,即 MainWindow.PlantsOfSelectedColor 属性。或者,例如如果您需要将 Page.DataContext 设置为不同的值,您可以让 Binding 遍历可视化树以使用 RelativeSource FindAncestor 查找 MainWindow.PlantsOfSelectedColorBinding.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>