1. ホーム
  2. .net

[解決済み] WPF DataGridのComboBoxColumnのItemsSourceのバインディング

2023-05-22 11:10:47

質問

2つのシンプルなモデルクラスとViewModelを持っています。

public class GridItem
{
    public string Name { get; set; }
    public int CompanyID { get; set; }
}

public class CompanyItem
{
    public int ID { get; set; }
    public string Name { get; set; }
}

public class ViewModel
{
    public ViewModel()
    {
        GridItems = new ObservableCollection<GridItem>() {
            new GridItem() { Name = "Jim", CompanyID = 1 } };

        CompanyItems = new ObservableCollection<CompanyItem>() {
            new CompanyItem() { ID = 1, Name = "Company 1" },
            new CompanyItem() { ID = 2, Name = "Company 2" } };
    }

    public ObservableCollection<GridItem> GridItems { get; set; }
    public ObservableCollection<CompanyItem> CompanyItems { get; set; }
}

...そしてシンプルなWindow。

<Window x:Class="DataGridComboBoxColumnApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <DataGrid AutoGenerateColumns="False" ItemsSource="{Binding GridItems}" >
            <DataGrid.Columns>
                <DataGridTextColumn Binding="{Binding Name}" />
                <DataGridComboBoxColumn ItemsSource="{Binding CompanyItems}"
                                    DisplayMemberPath="Name"
                                    SelectedValuePath="ID"
                                    SelectedValueBinding="{Binding CompanyID}" />
            </DataGrid.Columns>
        </DataGrid>
    </Grid>
</Window>

ViewModelにMainWindowの DataContext をApp.xaml.csに記述しています。

public partial class App : Application
{
    protected override void OnStartup(StartupEventArgs e)
    {
        base.OnStartup(e);

        MainWindow window = new MainWindow();
        ViewModel viewModel = new ViewModel();

        window.DataContext = viewModel;
        window.Show();
    }
}

見ての通り、私は ItemsSource をデータグリッドの GridItems コレクションに追加します。この部分は動作し、Name "Jim"を持つ単一のGrid行が表示されます。

また ItemsSource を設定したい。 CompanyItems コレクションに追加します。この部分はうまくいきません。ComboBox は空のままで、Debugger Output Window にエラー メッセージが表示されます。

System.Windows.Data Error: 2 : Cannot 管理された FrameworkElement または 要素のための FrameworkContentElement 要素が見つかりません。 BindingExpression:Path=CompanyItems; DataItem=null; ターゲットエレメントは 'DataGridComboBoxColumn' です。 (HashCode=28633162); ターゲットプロパティ は'ItemsSource'(タイプ'IEnumerable')

私は、WPFが期待するのは CompanyItems のプロパティとして GridItem のプロパティであり、それがバインディングに失敗する理由です。

すでに動作させてみたところ RelativeSourceAncestorType のように

<DataGridComboBoxColumn ItemsSource="{Binding CompanyItems, 
    RelativeSource={RelativeSource Mode=FindAncestor,
                                   AncestorType={x:Type Window}}}"
                        DisplayMemberPath="Name"
                        SelectedValuePath="ID"
                        SelectedValueBinding="{Binding CompanyID}" />

しかし、これではデバッガの出力で別のエラーが発生します。

System.Windows.Data Error: 4 : できません 参照でバインディングのソースを見つけることができません。 'RelativeSource FindAncestor, AncestorType='System.Windows.Window', AncestorLevel='1''. BindingExpression:Path=CompanyItems; DataItem=null; ターゲットエレメントは 'DataGridComboBoxColumn'です。 (HashCode=1150788); ターゲットプロパティは 'ItemsSource' (タイプ 'IEnumerable') です。

質問です。DataGridComboBoxColumnのItemsSourceをViewModelのCompanyItemsコレクションにバインドするにはどうしたらよいですか?それはまったく可能ですか?

事前に助けをありがとうございました

どのように解決するのですか?

Plsは、以下のDataGridComboBoxColumn xamlがあなたのために動作するかどうかを確認してください。

<DataGridComboBoxColumn 
    SelectedValueBinding="{Binding CompanyID}" 
    DisplayMemberPath="Name" 
    SelectedValuePath="ID">

    <DataGridComboBoxColumn.ElementStyle>
        <Style TargetType="{x:Type ComboBox}">
            <Setter Property="ItemsSource" Value="{Binding Path=DataContext.CompanyItems, RelativeSource={RelativeSource AncestorType={x:Type Window}}}" />
        </Style>
    </DataGridComboBoxColumn.ElementStyle>
    <DataGridComboBoxColumn.EditingElementStyle>
        <Style TargetType="{x:Type ComboBox}">
            <Setter Property="ItemsSource" Value="{Binding Path=DataContext.CompanyItems, RelativeSource={RelativeSource AncestorType={x:Type Window}}}" />
        </Style>
    </DataGridComboBoxColumn.EditingElementStyle>
</DataGridComboBoxColumn>

ここでは、あなたが直面している問題に対する別の解決策を見つけることができます。 WPFのDataGridでコンボボックスを使用する