Wpf - 绑定一个gridcontrol选择的行数据并将其填入另一个gridcontrol

时间:2017-04-06 11:18:57

标签: c# wpf

我有一个不同字段的gridcontrol,我在代码中没有提到

<dxg:GridControl   HorizontalAlignment="Stretch" Height="300"  VerticalAlignment="Top" x:Name="grid1"  AutoPopulateColumns="False" ItemsSource="{Binding Collection1}"    >
                    <dxg:GridControl.View >
                        <dxg:TableView x:Name="TableView1" />
                    </dxg:GridControl.View>
                .   
                .   
                .   
                .

我在同一页面上有另外一个网格控件,包含各种字段

<dxg:GridControl HorizontalAlignment="Stretch" Height="250"  VerticalAlignment="Top" x:Name="grid2"  AutoPopulateColumns="False"
                                 ItemsSource="{Binding ElementName="TableView1" ,path=Collection2.FocusedRow}"    >
                    <dxg:GridControl.View >
                        <dxg:TableView x:Name="TableView2"  />
                    </dxg:GridControl.View>
                .   
                .   
                .   
                .

现在collection1 Id 是主键,collection2 colID 是外键,它们彼此都有关系

此处的场景是,如果我在grid1中选择一行,则所有相应的记录必须显示在网格2中

 public class myCollection: BindingList<orders>
{
     public DataContext dc;

    public myCollection(IList<orders> list)
        : base(list)
    {
    }

    protected override void RemoveItem(int index)
    {
        orders deleteItem = this.Items[index];

        if (Dc.Order != null)
        {
            Dc.Order.DeleteOnSubmit(deleteItem);
        }
        base.RemoveItem(index);
    }

}
  

我的订单通用类和master的泛型类是相同的

2 个答案:

答案 0 :(得分:1)

如果我说XAML属性,这里你想根据1st Datagrid的SelectedItem属性更新2nd Datagrid的ItemsSource属性。

要实现此目的,请添加一个新属性&#34; SelectedItemDg1&#34;在ViewModel中,它将保存第一个DataGrid的选择。在Setter of this&#34; SelectedItemDg1&#34;属性,根据您的需要设置Collection2。

确保实现INotifyPropertyChanged接口并对两个集合使用ObservableCollection类型。

以下是相同的代码示例:

  

模型类:

public class Country
{
    public string CountryName { get; set; }

    public int CountryId { get; set; }

    public List<State> States { get; set; }
}

public class State
{
    public string StateName { get; set; }
    public int StateId { get; set; }
}
  

ViewModel:

public class MainWindowViewModel : INotifyPropertyChanged
{

    public MainWindowViewModel()
    {
        CountriesCollection = new ObservableCollection<Country>();
        StateCollection = new ObservableCollection<State>();
        LoadData();
    }

    private ObservableCollection<Country> _CountriesCollection;

    public ObservableCollection<Country> CountriesCollection
    {
        get { return _CountriesCollection; }
        set
        {
            _CountriesCollection = value;
            NotifyPropertyChanged("CountriesCollection");
        }
    }

    private ObservableCollection<State> _StatesCollection;

    public ObservableCollection<State> StateCollection
    {
        get { return _StatesCollection; }
        set
        {
            _StatesCollection = value;
            NotifyPropertyChanged("StateCollection");
        }
    }

    private Country _SelectedCountry;

    public Country SelectedCountry
    {
        get { return _SelectedCountry; }
        set
        {
            _SelectedCountry = value;
            if (_SelectedCountry != null && _SelectedCountry.States != null)
            {
                StateCollection = new ObservableCollection<State>(_SelectedCountry.States);
            }
            NotifyPropertyChanged("SelectedCountry");
        }
    }

    private void LoadData()
    {
        if (CountriesCollection != null)
        {
            CountriesCollection.Add(new Country
            {
                CountryId = 1,
                CountryName = "India",
                States = new List<State>
                            {
                                    new State { StateId = 1, StateName = "Gujarat"},
                                    new State { StateId = 2, StateName = "Punjab"},
                                    new State { StateId = 3, StateName = "Maharastra"}
                            }
            });
            CountriesCollection.Add(new Country
            {
                CountryId = 2,
                CountryName = "Chine",
                States = new List<State>
                            {
                                    new State { StateId = 4, StateName = "Chine_State1"},
                                    new State { StateId = 5, StateName = "Chine_State2"},
                                    new State { StateId = 6, StateName = "Chine_State3"}
                            }
            });
            CountriesCollection.Add(new Country
            {
                CountryId = 3,
                CountryName = "japan",
                States = new List<State>
                            {
                                    new State { StateId = 7, StateName = "Japan_State1"},
                                    new State { StateId = 8, StateName = "Japan_State2"},
                                    new State { StateId = 9, StateName = "Japan_State3"}
                            }
            });
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    private void NotifyPropertyChanged(String info)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(info));
    }

}
  

XALM:

 <StackPanel Orientation="Horizontal" >
    <DataGrid AutoGenerateColumns="True" 
              Height="300" Width="300" 
              HorizontalAlignment="Left" Margin="30" 
              ItemsSource="{Binding CountriesCollection}" 
              SelectedItem="{Binding SelectedCountry}">

    </DataGrid>
    <DataGrid AutoGenerateColumns="True" 
              Height="300" Width="300" 
              HorizontalAlignment="Left" Margin="30"  
              ItemsSource="{Binding SelectedCountry.States}">

    </DataGrid>
</StackPanel>

这里我有DataGrid的AutoGenerateColumns属性,但你必须根据你的要求进行更改。

我希望这个示例代码能让您轻松理解。

答案 1 :(得分:0)

我发现在集合上执行此类主要细节绑定的最简单和最干净的方法是将ObservableCollection包装在一个类中,公开其ListCollectionView并将ItemsSource绑定到它,如下所示(它有一些用于简化xml序列化的额外代码):

public class ViewableCollection<T> : ObservableCollection<T>
{
    private ListCollectionView _View;

    public ViewableCollection(IEnumerable<T> items)
        : base(items) { }

    public ViewableCollection()
        : base() { }

    [XmlIgnore]
    public ListCollectionView View
    {
        get
        {
            if (_View == null)
            {
                _View = new ListCollectionView(this);
                _View.CurrentChanged += new EventHandler(InnerView_CurrentChanged);
            }
            return _View;
        }
    }

    [XmlIgnore]
    public T CurrentItem
    {
        get
        {
            return (T)this.View.CurrentItem;
        }
        set
        {
            this.View.MoveCurrentTo(value);
        }
    }

    private void InnerView_CurrentChanged(object sender, EventArgs e)
    {
        this.OnPropertyChanged(new PropertyChangedEventArgs("CurrentItem"));
    }

    public void AddRange(IEnumerable<T> range)
    {
        if (range == null)
            throw new ArgumentNullException("range");

        foreach (T item in range)
        {
            this.Items.Add(item);
        }

        this.OnPropertyChanged(new PropertyChangedEventArgs("Count"));
        this.OnPropertyChanged(new PropertyChangedEventArgs("Item[]"));
        this.OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, (IList)range.ToList()));
    }

    public void ReplaceItems(IEnumerable<T> range)
    {
        if (range == null)
            throw new ArgumentNullException("range");

        this.Items.Clear();
        foreach (T item in range)
        {
            this.Items.Add(item);
        }

        this.OnPropertyChanged(new PropertyChangedEventArgs("Count"));
        this.OnPropertyChanged(new PropertyChangedEventArgs("Item[]"));
        this.OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
    }

    public void RemoveItems(IEnumerable<T> range)
    {

        if (range == null)
            throw new ArgumentNullException("range");

        foreach (T item in range)
        {
            this.Items.Remove(item);
        }

        this.OnPropertyChanged(new PropertyChangedEventArgs("Count"));
        this.OnPropertyChanged(new PropertyChangedEventArgs("Item[]"));
        this.OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, (IList)range.ToList()));
    }

    public void ClearAll()
    {
        IList old = this.Items.ToList();
        base.Items.Clear();
        this.OnPropertyChanged(new PropertyChangedEventArgs("Count"));
        this.OnPropertyChanged(new PropertyChangedEventArgs("Item[]"));
        this.OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, old));
    }

    public void CallCollectionChaged()
    {
        this.OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
    }

    // necessary for xml easy serialization using [XmlArray] attribute
    public static implicit operator List<T>(ViewableCollection<T> o)
    {
        return o == null ? default(List<T>) : o.ToList();
    }

    // necessary for xml easy serialization using [XmlArray] attribute
    public static implicit operator ViewableCollection<T>(List<T> o)
    {
        return o == default(List<T>) || o == null ? new ViewableCollection<T>() : new ViewableCollection<T>(o);
    }
}

然后在ViewModel中(请记住实施INotifyPropertyChanged,我使用nuget包Fody.PropertyChanged在属性上自动实现它):

[ImplementPropertyChanged]
public class MyViewModel
{
    public ViewableCollection<MySecondViewModel> Collection1 { get; set; }

    public MyViewModel()
    {
        this.Collection1 = new ViewableCollection<MySecondViewModel>();
    }
}

[ImplementPropertyChanged]
public class MySecondViewModel
{ 
    public string MyColumn1 { get; set; }
    public string MyColumn2 { get; set; }
    public ViewableCollection<MyThirdViewModel> Collection2 { get; set; }

    public MySecondViewModel()
    {
        this.Collection1 = new ViewableCollection<MyThirdViewModel>();
    }
}

[ImplementPropertyChanged]
public class MyThirdViewModel
{ 
    public string MyColumn1 { get; set; }
    public string MyColumn2 { get; set; }
}

//...
this.DataContext = new MyViewModel();

然后,保持网格同步就像这样简单:

<DataGrid ItemsSource="{Binding Collection1.View, Mode=OneWay}" 
          IsSynchronizedWithCurrentItem="True" />
<DataGrid ItemsSource="{Binding Collection1.CurrentItem.Collection2.View, Mode=OneWay}"
          IsSynchronizedWithCurrentItem="True" />

例如,绑定到当前所选Column1中当前所选项目中的Collection2属性将为:

<TextBlock Text="{Binding Collection1.CurrentItem.Collection2.CurrentItem.Column1}" />

此外,您可以在后面的代码中管理选择,例如:

Collection1.CurrentItem=null;

将清除集合上的选择。

您还可以从后面的代码中对ViewableCollection进行排序(以及过滤和分组),如下所示:

Collection1.View.SortDescriptions.Add(new SortDescription("Column1",ListSortDirection.Ascending));

请记住,在实例化之后你不应该替换整个ViewableCollection,只需添加/删除项目(为此目的,方法AddRangeReplaceItems用于批量添加/替换项目而不会不必要地增加CollectionChanged个事件