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で定義された4つのオブジェクト、、、、、、および、はすべて20WindowStackPanelあり、クラスのインスタンスがそれらのプロパティに割り当てられます。したがって、すべてのバインディング(、、、またはが指定されたバインディングを除く)は、そのインスタンスに対して解決されます。TextBoxCheckBoxFontSizeViewModelDataContextElementNameRelativeSourceSource

プロパティが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インターフェイスを実装し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にも適用できることに注意してください。3つのXAMLベースのフレームワークのどれを使用しているかを指定しなかったので、私が最もよく知っているWPFフレームワークを投稿しました。

于 2013-03-10T14:22:19.193 に答える