【问题标题】:Loaded XAML Not Binding to Existing Elements Correctly加载的 XAML 未正确绑定到现有元素
【发布时间】:2011-03-18 12:18:36
【问题描述】:

我有一个按钮,可以从文件加载 XAML,从中创建一个控件,然后将此控件作为子控件添加到画布中,该画布是窗口停靠面板资源中存在的模板的一部分。该窗口还有一个名为 cboTColour 的组合框和一个名为 cboBColour 的组合框,我用它们在加载的控件上设置简单的渐变背景。

我使用以下代码加载 XAML 并将其添加到我的画布中:

XmlReader xaml = XmlReader.Create(filename);
newControl = (Viewbox)XamlReader.Load(xaml);
((Canvas)(testButton.Template.FindName("MyCanvas", testButton))).Children.Clear();
((Canvas)(testButton.Template.FindName("MyCanvas", testButton))).Children.Add(newControl);

这是我加载的 XAML:

<?xml version="1.0" encoding="utf-8"?>
<Viewbox xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" x:Name="Document" Stretch="Fill">
    <Canvas Height="64" Width="128" ClipToBounds="True">
        <Canvas.Background>
            <!--Horizontal Gradient-->
            <LinearGradientBrush StartPoint="1,0">
                <GradientStop Color="{Binding ElementName=cboTColour, Path=SelectedItem.Name}" Offset="0"></GradientStop>
                <GradientStop Color="{Binding ElementName=cboBColour, Path=SelectedItem.Name}" Offset="1"></GradientStop>
            </LinearGradientBrush>
        </Canvas.Background>
    </Canvas>
</Viewbox>

我已经尝试将 XAML 直接放入设计器中,它运行良好,所以这不是问题。当我从文件加载 XAML 时,正在创建并正确放置控件,但数据绑定不起作用 - 颜色不会改变。我收到以下错误:

System.Windows.Data Error: 4 : Cannot find source for binding with reference 'ElementName=cboTColour'. BindingExpression:Path=SelectedItem.Name; DataItem=null; target element is 'GradientStop' (HashCode=24393646); target property is 'Color' (type 'Color')
System.Windows.Data Error: 4 : Cannot find source for binding with reference 'ElementName=cboBColour'. BindingExpression:Path=SelectedItem.Name; DataItem=null; target element is 'GradientStop' (HashCode=23972246); target property is 'Color' (type 'Color')

我假设发生的情况是当 XAMLReader 加载 xaml 广告从中创建控件时,它不确定我的组合框的路径,因为 xaml 还不是窗口的一部分,并且当控件是添加到窗口中,此绑定不会更新,但我不知道如何修改 XAML 中的绑定以反映我的组合框与其相关的位置,或者修改 XAMLReader 或整体数据上下文考虑到我的控制。我还可以向您保证,当在组合框所在的窗口上按下按钮时代码运行时,此时已经创建了组合框。

我必须指定我不能在代码中修改绑定本身,因为绑定将出现在我将加载的不同 XAML 文件中的不同位置和不同时间。

任何帮助将不胜感激。

【问题讨论】:

    标签: c# wpf data-binding xaml binding


    【解决方案1】:

    看起来 XamlReader 对其加载的 xaml 设置了限制,因此它不能包含未在加载的 xml 中定义的未知元素名称。而是使用数据绑定到可以正常工作但需要一些代码的属性。当用户更改组合框的选定项时,下面的代码将更改加载控件的背景。您需要添加一个值转换器,将颜色转换为可供组合框使用的人类可读名称。

    XAML:

    <StackPanel>
        <ComboBox 
            ItemsSource="{Binding Path=AvailableColors}" 
            SelectedValuePath="Color"
            SelectedValue="{Binding Path=SelectedColors[color0].Color}" />
        <ComboBox 
            ItemsSource="{Binding Path=AvailableColors}" 
            SelectedValuePath="Color"
            SelectedValue="{Binding Path=SelectedColors[color1].Color}" />
        <ContentControl Name="newControl" />
    </StackPanel>
    

    后面的代码:

    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Linq;
    using System.Windows;
    using System.Windows.Markup;
    using System.Windows.Media;
    using System.Xml;
    
    namespace LoadTest
    {
        public partial class Window1 : Window
        {
            public Window1()
            {
                InitializeComponent();
    
                SelectedColors = new Dictionary<string, ColorInfo>();
                SelectedColors.Add("color0", AvailableColors.First());
                SelectedColors.Add("color1", AvailableColors.Last());
    
                XmlReader xaml = XmlReader.Create("newcontrol.xml");
                newControl.Content = XamlReader.Load(xaml);
                newControl.DataContext = SelectedColors;
    
                DataContext = this;
            }
    
            public List<ColorInfo> AvailableColors
            {
                get
                {
                    return new List<ColorInfo>()
                    {
                        new ColorInfo() {Color = Colors.Red },
                        new ColorInfo() { Color = Colors.Green },
                        new ColorInfo() { Color = Colors.Blue },
                        new ColorInfo() { Color = Colors.Yellow }
                    };
                }
            }
    
            public Dictionary<string, ColorInfo> SelectedColors { get; private set;}
        }
    
        public class ColorInfo : INotifyPropertyChanged
        {
            private Color _color;
            public Color Color
            {
                get { return _color; }
                set 
                {
                    _color = value;
                    if (PropertyChanged != null)
                    {
                        PropertyChanged(this, new PropertyChangedEventArgs("Color"));
                    }
                }
            }
    
            public event PropertyChangedEventHandler PropertyChanged;
        }
    }
    

    要加载的 XAML 文件 (newcontrol.xml):

    <?xml version="1.0" encoding="utf-8"?>
    <Viewbox
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      x:Name="Document" Stretch="Fill">
      <Canvas Height="64" Width="128" ClipToBounds="True">
        <Canvas.Background>
          <LinearGradientBrush StartPoint="1,0">
            <GradientStop Color="{Binding Path=[color0].Color}" Offset="0" />
            <GradientStop Color="{Binding Path=[color1].Color}" Offset="1" />
          </LinearGradientBrush>
        </Canvas.Background>
      </Canvas>
    </Viewbox>
    

    【讨论】:

      猜你喜欢
      • 2019-03-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-10-07
      相关资源
      最近更新 更多