1

メインのWPFフォームにドッキングしているユーザーコントロールのデータグリッドビューをバインドしたいと思います。ただし、データをバインドしようとするたびに、データが事前に存在している必要があり、更新されません。コードビハインドではなく、イベントがトリガーされてdatagridviewを更新するタイミングを知るために、XAMLでこれを直接実行する方法はありますか?

XAMLの部分コード:

xmlns:c="clr-namespace:TestWPFMain"

<UserControl.Resources>
    <c:GridData x:Key="dataforGrid"/>
</UserControl.Resources>
<Grid>
    <DataGrid Grid.Row="2" x:Name="datagridMain" ItemsSource="{Binding Source={StaticResource dataforGrid}, Path=Results, Mode=TwoWay}" />
</Grid>

上記のUserControlのコードビハインド:

public GridControl()
    {
        InitializeComponent();

        GridData gd = new GridData();
        gd.UpdateResults();

        //datagridMain.ItemsSource = gd.Results;  
        -- This code above will work if I uncomment but I want it to be bound 
           directly and was curious as I thought the mode of 'two way' would 
           do this.  I am not certain and most examples assume property is already
           set up and not being created and updated.
    }

GridDataのコードクラス:

class PersonName
{
    public string Name { get; set; }
}

class GridData
{
    public ObservableCollection<PersonName> Results { get; set; }

    public void UpdateResults()
    {
        using (EntityDataModel be = new EntityDataModel())
        {
            var list = be.tePersons.Select(x => new PersonName { Name = x.FirstName });

            Results = new ObservableCollection<PersonName>(list);
        }
    }
}
4

2 に答える 2

1

このようなバインディングを使用するには、次のことを行う必要があります。

  1. (またはその親の1つに)DataContext正しく設定するDataGrid
  2. モデルクラスに実装し、プロパティセッターINotifyPropertyChangedでレイズします。PropertyChanged

1)

ウィンドウのDataContextをGridDataオブジェクトに設定します。

public GridControl()
{
    InitializeComponent();

    GridData gd = new GridData();
    gd.UpdateResults();
    this.DataContext = gd;
}

2)

を実装しINotifyPropertyChangedます。Resultsこれにより、プロパティが更新されたときにビューが確実に通知されます。

public class GridData : INotifyPropertyChanged
{
    private ObservableCollection<PersonName> _results;
    public ObservableCollection<PersonName> Results 
    {  
        get { return _results; }
        set
        {
            _results = value;
            RaisePropertyChanged("GridData");
        }
    }

    // ...

    #region INotifyPropertyChanged
    public event PropertyChangedEventHandler PropertyChanged;
    private void RaisePropertyChanged(string prop)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(prop));
        }
    }
    #endregion
}

次に、データコンテキストに関連するパスにバインドするだけです。

<DataGrid ItemsSource="{Binding Results}" />

この場合、双方向のバインドは必要ないことに注意してください。これは、ビューからモデルに変更を伝播するためです(つまり、テキストボックスやチェックボックスなどのUIコントロールがある場合に最も役立ちます)。

于 2012-12-04T01:12:23.903 に答える
1

これが例です(私はWindowを使用しましたが、UserControlでも同じように機能します)

Xaml:

<Window x:Class="WpfApplication4.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" Name="UI">
    <Grid>
        <DataGrid Grid.Row="2" x:Name="datagridMain" ItemsSource="{Binding ElementName=UI, Path=GridData.Results, Mode=TwoWay}" />
    </Grid>
</Window>

または、DataContext全体が必要なID:

<Window x:Class="WpfApplication4.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" Name="UI">
    <Grid>
        <DataGrid Grid.Row="2" x:Name="datagridMain" DataContext="{Binding ElementName=UI, Path=GridData}" ItemsSource="{Binding Results}" />
    </Grid>
</Window>

コード:

INotifyPropertyChangedを実装して、GridDataが変更されたことをxamlが認識できるようにする必要があります。この関数が組み込まれているため、GridData内のObservableCollectionは、削除アイテムを追加するたびにDataGridコントロールを更新します。

public partial class MainWindow : Window , INotifyPropertyChanged
{
    public MainWindow()
    {
        InitializeComponent();
        GridData = new GridData { Results = new ObservableCollection<PersonName>() };
        GridData.Results.Add(new PersonName { Name = "Test1" });
        GridData.Results.Add(new PersonName { Name = "Test2" });
    }

    private GridData _gridData;
    public GridData GridData
    {
        get { return _gridData; }
        set { _gridData = value; NotifyPropertyChanged("GridData"); }
    }

    public event PropertyChangedEventHandler PropertyChanged;
    /// <summary>
    /// Notifies the property changed.
    /// </summary>
    /// <param name="info">The info.</param>
    public void NotifyPropertyChanged(String info)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(info));
        }
    }
}

クラス:updateメソッドに小さな変更を加えたので、既存のObservableCollectionをクリアして更新するだけです。そうしないと、新しいObservableCollectionを割り当てる場合に、このクラスにINotifypropertyChangedを実装する必要があります。

public class PersonName
{
    public string Name { get; set; }
}

public class GridData
{
    public GridData()
    {
       Results = new ObservableCollection<PersonName>()
    }

    public ObservableCollection<PersonName> Results { get; set; }

    public void UpdateResults()
    {
        using (EntityDataModel be = new EntityDataModel())
        {
            // Just update existing list, instead of creating a new one.
           Results.Clear();
           be.tePersons.Select(x => new PersonName { Name = x.FirstName }).ToList().ForEach(item => Results.Add(item);
        }
    }
}
于 2012-12-04T01:18:28.223 に答える