1

好的,我们现在正在为我们的 GUI 尝试 XAML(并且边走边学)......我已经能够在 XAML 和 C# 中相互独立地进行数据绑定而不会出现问题,但现在是我需要的时候了来回传递值,我有点迷茫。当我编译并尝试导航到页面时,它会抛出 XamlParseException:指定的类名与实际的根实例类型不匹配。删除 Class 指令或通过 XamlObjectWriterSettings.RootObjectInstance 提供实例。第 5 行位置 2。

非常感谢任何帮助或在正确方向上轻轻推动:)

这就是我所在的位置:

namespace TheAirline.GraphicsModel.PageModel.PageFinancesModel
{
    /// <summary>
    /// Interaction logic for PageFinances.xaml
    /// </summary>
    public partial class PageFinances : Page
    {
        private Airline Airline;

        public PageFinances(Airline airline)
        {
            InitializeComponent();
            this.Language = XmlLanguage.GetLanguage(new   CultureInfo(AppSettings.GetInstance().getLanguage().CultureInfo, true).IetfLanguageTag);

            this.Airline = airline;
            Page page = null;
//loading the XAML
          using (FileStream fs = new FileStream("TheAirline\\GraphicsModel\\PageModel  \\PageFinancesModel\\PageFinances.xaml", FileMode.Open, FileAccess.Read))
            {
            page = (Page)XamlReader.Load(fs);
            }
//finding XAML element and trying to set the value to a variable
          string airlineCash = GameObject.GetInstance().HumanAirline.Money.ToString();
          TextBox cashValue = (TextBox)page.FindName("cashValue");
          cashValue.DataContext = airlineCash;
        }
    }
}

XAML 的前几行:

<Page
    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:AirlineModel="clr-namespace:TheAirline.Model.AirlineModel"
    mc:Ignorable="d"
x:Class="TheAirline.GraphicsModel.PageModel.PageFinancesModel.PageFinances"
    xmlns:c="clr-namespace:TheAirline.GraphicsModel.Converters"
...>
</Page>
4

1 回答 1

1

XAML 中的绑定DataContext针对分配给任何给定 XAML 元素的属性的对象进行解析。该属性(以及许多其他属性)的值在任何给定的可视树中从父元素继承到子元素。

例如,给定这个类:

public namespace MyNamespace
{
    public class ViewModel
    {
        public string Name {get;set;}
        public bool IsActive {get;set;}
    }
}

和这个 XAML:

<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:MyNamespace"
        FontSize="20">
   <Window.DataContext>
       <local:ViewModel>
   </Window.DataContext>
   <StackPanel>
       <TextBox Text="{Binding Path=Name}"/>
       <CheckBox IsChecked="{Binding Path=IsActive}"/>
   <StackPanel>
</Window>

XAML 中定义的所有四个对象,the Window、the StackPanel、theTextBox和 the CheckBox,都将具有FontSize20 的 a,并且将类的实例ViewModel分配给它们的DataContext属性。因此,所有绑定(带有指定ElementNameRelativeSource或的绑定除外Source)都将针对该实例进行解析。

如果属性是在代码中而不是在 XAML 中分配的,那将是完全相同的:

public MyWindow() //Window Constructor
{
    InitializeComponent();
    this.DataContext = new ViewModel(); //Note that keyword "this" is redundant, I just explicity put it there for clarity.
}

正因为如此,不需要DataContext显式地为每个元素设置属性,因为框架已经处理好了。

此外,请注意,在 XAML 中,大多数内置标记扩展都有一个默认构造函数约定,允许您缩写它们的用法。在Binding Markup Extension的情况下,默认构造函数具有该Path属性,因此:

<TextBox Text="{Binding Path=Name}"/>

与此完全相同:

<TextBox Text="{Binding Name}"/>

现在,为了使基础 DataContext 中的属性更改自动从绑定源 ( ViewModel) 传递到绑定目标(XAML 定义的对象),源对象必须实现接口并在每次属性更改时System.ComponentModel.INotifyPropertyChanged引发事件。PropertyChanged

因此,为了支持双向绑定,示例类应如下所示:

public namespace MyNamespace
{
    public class ViewModel: INotifyPropertyChanged
    {
        private string _name;
        public string Name 
        {
            get
            {
                return _name;
            }
            set
            {
                _name = value;
                NotifyPropertyChanged("Name");
            }
        }

        private bool _isActive;
        public bool IsActive
        {
            get
            {
                return _isActive;
            }
            set
            {
                _isActive = value;
                NotifyPropertyChanged("IsActive");
            }
        }
    }

    public void NotifyPropertyChanged (string propertyName)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName);
    }
}

请注意,ViewModel该类不依赖或直接引用任何 XAML 定义的对象,但它仍然包含将出现在 UI 中的属性的值。这允许 UI 和应用程序逻辑/数据(称为MVVM Pattern. 如果您希望在 C# + XAML 编程中取得成功,我强烈建议您研究该主题,因为与其他传统 UI 范例相比,它是一种彻底的思维转变。

例如,在基于 XAML 的应用程序中不推荐这样的事情:

if (myWindow.CheckBox1.IsChecked)
    //Do Something

因为这意味着您正在耦合应用程序逻辑并使其依赖于 UI 元素的状态,而这正是您需要避免的。

请注意,此答案中引用的所有链接和所有概念都与 WPF 有关,但也适用于 Silverlight 和 WinRT。由于您没有指定您使用的是三个基于 XAML 的框架中的哪一个,因此我发布了 WPF 框架,这是我最熟悉的。

于 2013-03-10T14:22:19.193 回答