WPFでのデータバインド式

WPFでのデータバインド式

データバインディングは、UI要素とビジネスモデル間のデータフローを可能にする強力なテクノロジーです。ビジネスモデル内のデータが変更されると、その変更が自動的にUI要素に反映されます。

最后更新 2021/10/18 16:53
Swati Gupta
预计阅读 8 分钟
分类
WPF
标签
.NET WPF Binding

バインディングの概念を議論し、StaticResourcesとDynamicResourcesのバインディングプロパティを使用する方法を説明する記事はたくさんあります。これらの概念はWPFが提供するデータバインド式を使用する。この記事では、WPFが提供するさまざまな種類のデータバインディング式を見ていきましょう。

プレゼンテーション:プレゼンテーション

データバインディングは、UI要素とビジネスモデル間のデータフローを可能にする強力なテクノロジーです。ビジネスモデル内のデータが変更されると、その変更が自動的にUI要素に反映されます。

Models Description
OneWay Source → Destination
TwoWay Source ←→ Destination
OneWayToSource Source ← Destination
OneTime Source → Destination (only once)

これは、WPFが提供するさまざまな種類のデータバインディング式で実現できます。

データバインド式の型は次のとおりです。

  • DataContextバインディング
  • RelativeSourceバインディング
  • ItemSourceバインディング#ItemSourceバインディング#

1.データコンテキストバインディング

Data Contextは依存属性であり、バインディングのデフォルトのソースです。Datacontextは論理ツリーに沿って継承します。したがって、論理ツリー内のすべての子要素を制御するためにDataContextを設定すると、別のソースが明示的に指定されない限り、同じDataContextも参照されます。

詳しく説明するために例を挙げましょう。

1.1次のようにクラスBookを作成します。

public class Book
{
    public string Name
    {
        get;
        set;
    }
    public string Author
    {
        get;
        set;
    }
}

1.2 添加一个 XAML 文件DataContextBinding.XAML并放置四个 TextBlock,如下所示。

<Grid VerticalAlignment="Center">
  <Grid.RowDefinitions>
    <RowDefinition Height="40" />
    <RowDefinition Height="40" />
  </Grid.RowDefinitions>
  <Grid.ColumnDefinitions>
    <ColumnDefinition Width="Auto" />
    <ColumnDefinition Width="Auto" />
  </Grid.ColumnDefinitions>
  <TextBlock Text="Book Name:" FontWeight="Bold" />
  <TextBlock Grid.Column="1" />
  <TextBlock Text="Author:" FontWeight="Bold" Grid.Row="1" />
  <TextBlock Grid.Row="1" Grid.Column="1" />
</Grid>

では、このDataContextプロパティを使用してデータを表示する方法を見てみましょう。

以下の2つの用途があります。

  • 1.式の使用

DataContextを直接バインドするために使用する。

クラスBookのインスタンスを作成し、そのプロパティを初期化し、クラスのNameプロパティをWindowのDataContextプロパティに割り当てます。

public partial class DataContextBinding: Window
{
    public DataContextBinding()
    {
        InitializeComponent();
        //Create the instance
        Book book = new Book();
        //initialize the properties
        book.Name = "Computer Networking";
        //Assign the Property as DataContext
        this.DataContext = book.Name;
    }
}

DataContextは論理ツリーとデータブックに沿って継承されるため、NameはControl Windowにバインドされます。Windowのすべての子要素も同じオブジェクト(book.Name)を参照します。

データを表示するには、以下のようにDataContextをTextblockにバインドします。

<TextBlock Text="Book Name:" FontWeight="Bold" />
<TextBlock Text="{Binding}" Grid.Column="1" />

輸出する。

  1. 式の使用

Datacontextのプロパティーをバインドします。

クラスBookのインスタンスを作成し、そのプロパティを初期化して、クラスのインスタンスBookをWindowのDataContextプロパティに割り当てます。

Book book = new Book();
//initialize the properties
book.Name = "Computer Networking";
book.Author = "James F. Kurose";
//Assign the instance as DataContext
this.DataContext = book;

では輸出を見てみましょう

バインド式はBook型のDataContextオブジェクトをバインドするために使用されるため、ToStringメソッドが呼び出され、データが文字列として表示されます。データを適切な形式で表示するには、次のようにデータオブジェクトのプロパティをTextBlockにバインドする必要があります。

<TextBlock Text="Book Name:" FontWeight="Bold" />
<TextBlock Text="{Binding Name}" Grid.Column="1" />
<TextBlock Text="Author:" FontWeight="Bold" Grid.Row="1" />
<TextBlock Text="{Binding Author}" Grid.Row="1" Grid.Column="1" />

バインド式 DataContextバインドのNameプロパティーをバインドします。

輸出する。

2)RelativeSource結合

RelativeSourceは、ターゲットをバインドするための相対関係を持つバインドソースを設定するプロパティです。この拡張機能は主に、要素の1つの属性を同じ要素の別の属性にバインドする必要がある場合に使用されます。

RelativeSourceには以下の4種類があります。

  1. Self
  2. FindAncestor
  3. TemplatedParent
  4. PreviousData

一つずつ詳しく見ていきましょう。

2.1 Self

Selfは、バインド元とバインド先が同じシーンで使用されます。オブジェクトの1つのプロパティは、同じオブジェクトの別のプロパティにバインドされます。

例えば、高さと幅が同じ楕円を考えてみましょう。

以下のコードをXAMLファイルに追加します。幅プロパティは、高さプロパティと相対的にバインドされています。

<Grid>
  <Ellipse
    Fill="Black"
    Height="100"
    Width="{Binding RelativeSource={RelativeSource Self},Path=Height}"
  >
  </Ellipse>
</Grid>

輸出する。

楕円の高さを変えると、幅も相対的に変化します。

2.2 FindAncestor

名前が示すように、このオプションは、バインディングソースがバインディングターゲットの祖先(親)の1つである場合に使用します。FindAncestor拡張機能を使用すると、あらゆるレベルの祖先を見つけることができます。

これをより明確に理解するために例を挙げましょう。

ステップは

以下に示す要素の論理ツリーを表すXAMLを作成します。

<Grid Name="Parent_3">
  <StackPanel Name="Parent_2">
    <Border Name="Parent_1">
      <StackPanel x:Name="Parent_0" Orientation="Vertical">
        <button></button>
      </StackPanel>
    </Border>
  </StackPanel>
</Grid>

次に、FindAncestor拡張機能を使用して、祖先のName属性を子要素buttonのContent属性にバインドしましょう。

<Grid Name="Parent_3">
  <StackPanel
    Name="Parent_2"
    HorizontalAlignment="Center"
    VerticalAlignment="Center"
    Width="100"
  >
    <Border Name="Parent_1">
      <StackPanel x:Name="Parent_0" Orientation="Vertical">
        <button
          Height="50"
          Content="{Binding RelativeSource={RelativeSource FindAncestor,  
AncestorType={x:Type StackPanel},  
AncestorLevel=2},Path=Name}"
        ></button>
      </StackPanel>
    </Border>
  </StackPanel>
</Grid>

輸出する。

AncestorTypeが“StackPanel”とAcestorLevelが“2”の組み合わせにより、ボタンのcontentプロパティとStackPanelのNameプロパティ(Parent_2)がバインドされます。

2.3 TemplatedParent

TemplatedParentは、未知の値を少量含むコントロールテンプレートを作成できるプロパティです。これらの値は、ControlTemplateが適用されるコントロールのプロパティによって異なります。

詳しく説明するために例を挙げましょう。

ステップは

  1. 次のようにボタン用のControlTemplateを作成します。
<Window.Resources>
  <ControlTemplate x:Key="template">
    <canvas>
      <Ellipse Height="110" Width="155" Fill="Black" />
      <Ellipse
        Height="100"
        Width="150"
        Fill="{Binding RelativeSource={RelativeSource TemplatedParent},Path=Background}"
      >
      </Ellipse>
      <ContentPresenter
        Margin="35"
        Content="{Binding RelativeSource={RelativeSource TemplatedParent},Path=Content}"
      />
    </canvas>
  </ControlTemplate>
</Window.Resources>

上記のコードでは、楕円のFillプロパティとContentPresenterのContentプロパティは、このテンプレートが適用されるコントロールのプロパティ値に依存しています。

  1. ボタンを追加し、テンプレートを適用します。
<button
  Margin="50"
  Background="Beige"
  Template="{StaticResource template}"
  Height="0"
  Content="Click me"
  FontSize="22"
></button>

テンプレートを適用すると、ボタンのBackground Beigeは楕円のFillプロパティに相対的にバインドされ、Content Click meはContentPresenterのContentプロパティに相対的にバインドされます。依存性値が有効になり、以下の出力が得られます。

輸出する。

2.4 PreviousData

これは比較的最小限の使用方法です。これは、データが分析されるときに発生し、以前のデータに対する値の変化を表現する必要があります。

詳しく説明するために例を挙げましょう。

ステップは

  1. クラスDataを作成し、次のようにINotifyPropertyChangedインタフェースを実装します。
public class Data: INotifyPropertyChanged
{
    public int DataValue
    {
        get;
        set;
    }
    public event PropertyChangedEventHandler PropertyChanged;
    protected void OnPropertyChanged(string PropertyName)
    {
        if (null != PropertyChanged)
        {
            PropertyChanged(this,
                new PropertyChangedEventArgs(PropertyName));
        }
    }
}
  1. データ型のリストを作成し、DataContextとして指定します。
public RelativeSourcePreviousData()
{
    InitializeComponent();
    List < Data > data = new List < Data > ();
    data.Add(new Data()
    {
        DataValue = 60
    });
    data.Add(new Data()
    {
        DataValue = 100
    });
    data.Add(new Data()
    {
        DataValue = 120
    });
    this.DataContext = data;
}
  1. XAMLファイルにItemsControlを追加します。
<ItemsControl ItemsSource="{Binding}"></ItemsControl>
  1. 次のようにItemsPanelテンプレートを作成します。
<ItemsControl ItemsSource="{Binding}">
  <ItemsControl.ItemsPanel>
    <ItemsPanelTemplate>
      <StackPanel Orientation="Vertical" />
    </ItemsPanelTemplate>
  </ItemsControl.ItemsPanel>
</ItemsControl>
  1. 次に、データを正しく表現するために、以下のようにDataTemplateを作成します。
<ItemsControl.ItemTemplate>
  <DataTemplate>
    <StackPanel Orientation="Horizontal">
      <Grid Margin="30,20,0,0">
        <Rectangle Width="80" Height="{Binding DataValue}" Fill="Blue" />
        <TextBlock
          Foreground="White"
          Margin="35,0,0,0"
          Text="{Binding DataValue}"
        ></TextBlock>
      </Grid>
      <TextBlock Margin="30,20,0,0" Text="Previous Data:"></TextBlock>
      <TextBlock
        VerticalAlignment="Center"
        Margin="5,20,0,0"
        Text="{Binding  
             RelativeSource={RelativeSource PreviousData}, Path=DataValue}"
      />
    </StackPanel>
  </DataTemplate>
</ItemsControl.ItemTemplate>

輸出する。

青いボックスの高さはリスト内のアイテムの値で、右側に古いデータが表示されます。この項目の最初の値は“60”です。最初の項目は古い値を持たない。

3、ItemSourceバインディング

コレクションを処理するときに使用します。このバインディング式を使用すると、SelectedItemのプロパティを簡単に読み取ることができます。スラッシュは、コレクション内の現在のアイテムを処理する特殊な演算子です。

以下に3つの表現を示す。

  1. {Binding / }
  2. {Binding Collection / }
  3. {Binding Collection / Property}

3.1 {Binding / }

この式は、DataContext内の現在のアイテムをバインドするために使用します。

例を挙げてみましょう:

以下の例では、DataContextは文字列型の国のコレクションであり、Listboxにバインドされています。

ステップは

  1. Countriesクラスを作成し、次に示すように、stringデータ型の国のコレクションを返すGetCountriesNameメソッドを追加します。
public class Countries
{
    public static List <string> GetCountriesName()
    {
        List <string> countries = new List <string> ();
        foreach(CultureInfo culture in CultureInfo.GetCultures(CultureTypes.SpecificCultures))
        {
            RegionInfo country = new RegionInfo(culture.LCID);
            if (!countries.Contains(country.EnglishName))
                countries.Add(country.EnglishName);
        }
        countries.Sort();
        return countries;
    }
}
  1. 以下のようにXAMlファイル、ListBox、Text Blockを追加します。
<DockPanel Name="Collection">
  <ListBox ItemsSource="{Binding}" IsSynchronizedWithCurrentItem="True">
  </ListBox>
  <TextBlock DockPanel.Dock="Top" />
</DockPanel>
  1. クラスCountriesのインスタンスを作成し、CountriesコレクションをDataContextとして指定します。
public CurrentItemCollection()
{
    InitializeComponent();
    Countries countries = new Countries();
    this.DataContext = countries.GetCountriesName()
}
  1. 次に示すように、TextBlockのTextプロパティーをバインドして、コレクションの現在選択されている項目にバインドします。
<TextBlock DockPanel.Dock="Top" Text="{Binding /}" />

輸出する。

リスト項目が選択されると、選択した国/地域が右側に表示されます。

3.2 {Binding Collection /}

この式は、DataContext内のコレクション属性の現在のアイテムをバインドするために使用されます。

例えば、

DataContextはCountriesクラス

CollectionプロパティーはCounriesListで、ListBoxにバインドされています。

ステップは

  1. 上記で作成した同様の国クラスを使用しますが、わずかに異なります。戻り値の型がRegionInfoのメソッドを作成します。
public static List <RegionInfo> GetCountries()
{
    List <RegionInfo> countries = new List <RegionInfo> ();
    foreach(CultureInfo culture in CultureInfo.GetCultures(CultureTypes.SpecificCultures))
    {
        RegionInfo country = new RegionInfo(culture.LCID);
        if (countries.Where(p => p.Name == country.Name).Count() == 0)
            countries.Add(country);
    }
    return countries.OrderBy(p => p.EnglishName).ToList();
}
  1. RegionInfo型のCountriesListプロパティーを追加します。
private List <RegionInfo> countries = null;
public List <RegionInfo> CountriesList
{
    get
    {
        if (countries == null)
            countries = GetCountries();
        return countries;
    }
}

以下はCountriesListコレクション内の値のスクリーンショットです。

  1. クラスCountriesをDataContextとして指定し、ListboxをDataContextのCountriesListプロパティーにバインドします。
<Window.Resources>
  <vm:Countries x:Key="Countries"></vm:Countries>
</Window.Resources>
<Grid>
  <DockPanel Name="Collection" DataContext="{StaticResource Countries}">
    <ListBox
      ItemsSource="{Binding CountriesList}"
      IsSynchronizedWithCurrentItem="True"
    >
      <ListBox.ItemTemplate>
        <DataTemplate>
          <TextBlock Text="{Binding EnglishName}"></TextBlock>
        </DataTemplate>
      </ListBox.ItemTemplate>
    </ListBox>
  </DockPanel>
</Grid>
  1. “CountriesList”プロパティーの現在の項目を計算するには、次のようにTextBlockの“Text”プロパティーをバインドします。
<TextBlock DockPanel.Dock="Top" Text="{Binding CountriesList/}" HorizontalAlignment="Center" FontSize="16" VerticalAlignment="Center" />

輸出する。

右側には、DataContext CountriesList内のコレクションの現在のアイテムCountriesListが表示されます。

3.3 {Binding Collection / Property}

この式は、DataContext内のコレクションの現在のアイテムのプロパティーをバインドするために使用されます。

たとえば、CountriesListコレクションの現在のアイテムの特定のプロパティを計算する必要がある場合などです。

この例では、プロパティ“English Name”の値を表示したいと思います。

これを行うには、以下のようにTextBlockのTextプロパティをバインドします。

<TextBlock DockPanel.Dock="Top" Text="{Binding CountriesList/EnglishName}" />

輸出する。

リスト内の項目が選択されたときに、プロパティ“English Name”の値が表示されるようになりました。

結論:結論

すべてのデータバインディング式を詳細に説明しました。WPFが提供するバインディングの概念と表現の理解に役立つことを願っています。


  • スワティ·グプタ著
  • 次の記事WPFにおけるデータバインディング表現
  • 原文へのリンク:https//www.c-sharpcorner.com/article/data-binding-expression-in-wpf/
  • オリジナルタイトル:Wolf at the End of Desert
Keep Exploring

延伸阅读

更多文章
同分类 / 同标签 2025/09/13

WPFからAvaloniaへの移行シリーズ:WPFプログラムをAvaloniaに移行する必要がある理由

ここ数年、当社のホストソフトウェアは主にWPFとWin Formで開発されてきました。これらのテクノロジーはWindowsプラットフォームで非常にうまく機能し、小規模なパイロット生産から今日の大規模なデリバリまでの段階を経てきました。しかし、ビジネスの成長と顧客のニーズの変化に伴い、単一のWindowsテクノロジースタックは私たちが乗り越えなければならないハードルになりました。

继续阅读
同分类 / 同标签 2025/01/26

WPFはカスタムXMLファイルで国際化を実現

この記事では、必要なNuGetパッケージのインストール、言語リストの動的取得、言語の動的切り替え、コードとxamlインターフェイスでの翻訳文字列の使用、開発者がWPFアプリケーションを簡単に国際化できるようにするソースコードへのリンクなど、WPFプログラムでカスタムXMLファイルを使用した国際化の方法について詳しく説明します。

继续阅读