【问题标题】:Loading XAML to C# for Data Binding将 XAML 加载到 C# 以进行数据绑定
【发布时间】:2013-03-10 00:11:57
【问题描述】:

好的,我们现在正在为我们的 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>

【问题讨论】:

  • 你的说法I have been able to do the data binding without a problem in XAML and C# independent of one another, but now comes the time I need to pass values back and forth and I'm a bit lost是完全矛盾的。如果您 DataBind,则 DataBinding ITSELF 正在来回传递数据。我不明白你的意思。此外,您不应该做TextBox cashValue = (TextBox)page.FindName("cashValue");cashValue.DataContext = airlineCash; 之类的事情。请说明您的需求,我们可以为您提供帮助。
  • 对不起,如果这有点含糊(而且自相矛盾) - 仍在学习 XAML 的来龙去脉。无论如何 - 我的意思是我能够将滑块的值绑定到 XAML 或 c# 中的文本框,但不能将在 XAML 中创建的值绑定到 c# 中的变量,反之亦然。我希望这更有意义:)

标签: c# xaml visual-studio-2012 .net-4.5


【解决方案1】:

XAML 中的Bindings 针对分配给任何给定 XAML 元素的 DataContext 属性的对象进行解析。从父元素到子元素的任何给定 Visual Tree 中该属性(以及许多其他属性)Is Inherited 的值。

例如,给定这个类:

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 中定义的所有四个对象,WindowStackPanelTextBoxCheckBox,将具有 20 个 FontSize,并分配 ViewModel 类的实例到他们的DataContext 财产。因此,所有绑定(带有指定 ElementNameRelativeSourceSource 的绑定除外)都将针对该实例进行解析。

如果属性是在代码中而不是在 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 中,大多数内置 Markup Extensions 都有一个默认构造函数约定,允许您缩写它们的用法。对于Binding Markup Extension,默认构造函数具有Path 属性,因此:

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

和这个完全一样:

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

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

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

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 框架,这是我最熟悉的。

【讨论】:

  • 感谢您的回答。我发现我在本地的问题相当简单,但你的回答提供了很多我还没有的背景信息:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多