none
WPF: Отображение изменений в DataGrid RRS feed

  • Вопрос

  • Имеется BBetList = ObservableCollection<BBet>. Элементы коллекции изменяются с помощью DataGrid1.

    В другом DataGrid2 мне необходимо выводить на экран отфильтрованную коллекцию BBetList. Для фильтрации создал:

    BBetsList = new ObservableCollection<BBet>();

                for (int i = 0; i < 17; i++)
                {
                    BBet B = new BBet(i, _resultstring[i]);
                    BBetsList.Add(B);
                }
                
                FilterBBets = new ListCollectionView(BBetsList);
                FilterBBets.Filter = new Predicate<object>(CollectionViewSource_Filter);

    BBetList биндится к DataGrid1

    FilterbBets биндится к DataGrid2

    В начальный момент, всё отображается нормально.

    Проблема в следующем. Когда изменяются данные в BBetList, надо каким то образом обновить FilterBBets. Я не знаю что делать. Помогите мне в этом вопросе

    13 июля 2011 г. 6:24

Ответы

  • Благодарю за ответ.

    К сожалению пока он мне не помог.

    Сделал я следующим образом:

    public class Bet : INotifyPropertyChanged
    {
        private ObservableCollection<BBet> _BBetsList;
        public ObservableCollection<BBet> BBetsList 
        {
          get
          {
            return _BBetsList;
          }
          set
          {
            _BBetsList = value;
            OnPropertyChanged("BBetsList");
            _FilterBBets = new ListCollectionView(_BBetsList);
            _FilterBBets.Filter = new Predicate<object>(CollectionViewSource_Filter);
          }
        }
        ListCollectionView _FilterBBets;
        public ListCollectionView FilterBBets 
        { 
          get 
          {
            //_FilterBBets.Refresh();
            return _FilterBBets; 
          }
          private set 
          {
            _FilterBBets = value;
            OnPropertyChanged("FilterBBets");
          }
        }
        public Bet(int _resultid)
        {      
          string[] _resultstring = { "0-0", "0-1", "0-2", "0-3", "1-0", "1-1", "1-2", "1-3", "2-0", "2-1", "2-2", "2-3", "3-0", "3-1", "3-2", "3-3", "NaN" };
          resultstring = _resultstring;
          active = false;
          resultid = _resultid;
          result = _resultstring[_resultid];
          MaxLBet = 0;
          MinLBet = 0;
          BBetsList = new ObservableCollection<BBet>();
          BBetsList.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(BBetsList_CollectionChanged);
          ((INotifyPropertyChanged)BBetsList).PropertyChanged += new PropertyChangedEventHandler(Bet_PropertyChanged);
    
          for (int i = 0; i < 1; i++)
          {
            BBet B = new BBet(i, _resultstring[i]);
            BBetsList.Add(B);
          }
        }
    
        void Bet_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
          MessageBox.Show("Property");
        }
    
        void BBetsList_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
        {
          MessageBox.Show("Collection");
        }
    
        private bool CollectionViewSource_Filter(object sender)
        {
          BBet B = sender as BBet;
    
          if (B == null || B.active == false)
            return false;
          else
          {        
            return true;
          }
        }
        
        #region INotifyPropertyChanged Members
        public event PropertyChangedEventHandler PropertyChanged;
        private void OnPropertyChanged(string name)
        {
          PropertyChangedEventHandler handler = PropertyChanged;
          if (handler != null)
          {
            handler(this, new PropertyChangedEventArgs(name));
          }
        }
        #endregion
      }
    
      public class BBet : INotifyPropertyChanged
      {
        private bool _active;
        public bool active 
        {
          get
          {
            return _active;
          }
          set
          {
            _active = value;
    
            OnPropertyChanged("active");
          }
        }
        public string result { get; private set; }
        public int resultid { get; set; }
        public double brate { get; set; }
    
        public BBet(int _resultid, string _result)
        {
          active = false;
          resultid = _resultid;
          result = _result;
        }
    
        public event PropertyChangedEventHandler PropertyChanged;
        private void OnPropertyChanged(string name)
        {
          PropertyChangedEventHandler handler = PropertyChanged;
          if (handler != null)
          {
            handler(this, new PropertyChangedEventArgs(name));
          }
        }
      }
    


    В XAML у меня DataGrid, к которому прибинден класс Bet, с одним полем типа DataGridTemplateColumn.

    В ресурсах описан вид полей следующим:

        <DataTemplate x:Key="BetBParamSet">
          <DataGrid AutoGenerateColumns="False" HeadersVisibility="None" ItemsSource="{Binding Path=BBetsList}" CanUserAddRows="False" RowEditEnding="DataGrid_RowEditEnding">
            <DataGrid.Columns>
              <DataGridCheckBoxColumn Binding="{Binding Path=active}"/>
              <DataGridTextColumn Binding="{Binding Path=result, Mode=OneWay}"/>
            </DataGrid.Columns>
          </DataGrid>
        </DataTemplate>
        <DataTemplate x:Key="BetParamView">
          <DataGrid AutoGenerateColumns="False" HeadersVisibility="None" ItemsSource="{Binding Path=FilterBBets}" CanUserDeleteRows="False" >
            <DataGrid.Columns>
              <DataGridCheckBoxColumn Binding="{Binding Path=active}"/>
              <DataGridTextColumn Binding="{Binding Path=result}" IsReadOnly="True"/>
              <DataGridTextColumn Binding="{Binding Path=brate}" IsReadOnly="True"/>
            </DataGrid.Columns>
          </DataGrid>
        </DataTemplate>
    


    В момент создания класса Bet происходит перехват событий и вывод на экран соответствующих сообщений. Когда же я начинаю редактировать таблицу, никаких сообщений не появляется. Соответственно, отследить наличие изменений не возможно.

     

    Относительно статьи в журнале. Я попытался аналогично сделать, но эффекта не получил. То есть, фильтрованная коллекция не изменялась.

     

    Единственное решение, которое я придумал и оно помогло, было следующим:

    ListCollectionView _FilterBBets;
    public ListCollectionView FilterBBets 
    { 
       get 
       {
         _FilterBBets.Refresh();
         return _FilterBBets; 
       }
       private set 
       {
         _FilterBBets = value;
         OnPropertyChanged("FilterBBets");
       }
     }
    


    В этом случае, коллекция обновлялась и результаты редактирования BBetsList корректно отображались.

    Хотелось бы всё таки выяснить, почему не сработал никак первый вариант.

    • Помечено в качестве ответа Sergey Rogachev 19 июля 2011 г. 12:36
    14 июля 2011 г. 8:35

Все ответы

  • Здравствуйте.

    Можете подписаться на события CollectionChanged и PropertyChanged и в их обработчиках выполнять нужную фильтрацию данных:

        public MainWindow()
        {
          InitializeComponent();
    
          ObservableCollection<object> test = new ObservableCollection<object>();
          test.CollectionChanged +=
            new System.Collections.Specialized.NotifyCollectionChangedEventHandler(test_CollectionChanged);
          ((INotifyPropertyChanged) test).PropertyChanged +=
            new PropertyChangedEventHandler(test_PropertyChanged);
        }
    
        void test_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
          //
        }
      
    
        void test_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
        {
          //
        }
    

    Также посмотрите на пост Sorts and filters on ObservableCollection, там можно загрузить тестовый проект и посмотреть как работает. Возможно это подойдет вам.

     


    Для связи [mail]
    13 июля 2011 г. 8:47
  • Благодарю за ответ.

    К сожалению пока он мне не помог.

    Сделал я следующим образом:

    public class Bet : INotifyPropertyChanged
    {
        private ObservableCollection<BBet> _BBetsList;
        public ObservableCollection<BBet> BBetsList 
        {
          get
          {
            return _BBetsList;
          }
          set
          {
            _BBetsList = value;
            OnPropertyChanged("BBetsList");
            _FilterBBets = new ListCollectionView(_BBetsList);
            _FilterBBets.Filter = new Predicate<object>(CollectionViewSource_Filter);
          }
        }
        ListCollectionView _FilterBBets;
        public ListCollectionView FilterBBets 
        { 
          get 
          {
            //_FilterBBets.Refresh();
            return _FilterBBets; 
          }
          private set 
          {
            _FilterBBets = value;
            OnPropertyChanged("FilterBBets");
          }
        }
        public Bet(int _resultid)
        {      
          string[] _resultstring = { "0-0", "0-1", "0-2", "0-3", "1-0", "1-1", "1-2", "1-3", "2-0", "2-1", "2-2", "2-3", "3-0", "3-1", "3-2", "3-3", "NaN" };
          resultstring = _resultstring;
          active = false;
          resultid = _resultid;
          result = _resultstring[_resultid];
          MaxLBet = 0;
          MinLBet = 0;
          BBetsList = new ObservableCollection<BBet>();
          BBetsList.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(BBetsList_CollectionChanged);
          ((INotifyPropertyChanged)BBetsList).PropertyChanged += new PropertyChangedEventHandler(Bet_PropertyChanged);
    
          for (int i = 0; i < 1; i++)
          {
            BBet B = new BBet(i, _resultstring[i]);
            BBetsList.Add(B);
          }
        }
    
        void Bet_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
          MessageBox.Show("Property");
        }
    
        void BBetsList_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
        {
          MessageBox.Show("Collection");
        }
    
        private bool CollectionViewSource_Filter(object sender)
        {
          BBet B = sender as BBet;
    
          if (B == null || B.active == false)
            return false;
          else
          {        
            return true;
          }
        }
        
        #region INotifyPropertyChanged Members
        public event PropertyChangedEventHandler PropertyChanged;
        private void OnPropertyChanged(string name)
        {
          PropertyChangedEventHandler handler = PropertyChanged;
          if (handler != null)
          {
            handler(this, new PropertyChangedEventArgs(name));
          }
        }
        #endregion
      }
    
      public class BBet : INotifyPropertyChanged
      {
        private bool _active;
        public bool active 
        {
          get
          {
            return _active;
          }
          set
          {
            _active = value;
    
            OnPropertyChanged("active");
          }
        }
        public string result { get; private set; }
        public int resultid { get; set; }
        public double brate { get; set; }
    
        public BBet(int _resultid, string _result)
        {
          active = false;
          resultid = _resultid;
          result = _result;
        }
    
        public event PropertyChangedEventHandler PropertyChanged;
        private void OnPropertyChanged(string name)
        {
          PropertyChangedEventHandler handler = PropertyChanged;
          if (handler != null)
          {
            handler(this, new PropertyChangedEventArgs(name));
          }
        }
      }
    


    В XAML у меня DataGrid, к которому прибинден класс Bet, с одним полем типа DataGridTemplateColumn.

    В ресурсах описан вид полей следующим:

        <DataTemplate x:Key="BetBParamSet">
          <DataGrid AutoGenerateColumns="False" HeadersVisibility="None" ItemsSource="{Binding Path=BBetsList}" CanUserAddRows="False" RowEditEnding="DataGrid_RowEditEnding">
            <DataGrid.Columns>
              <DataGridCheckBoxColumn Binding="{Binding Path=active}"/>
              <DataGridTextColumn Binding="{Binding Path=result, Mode=OneWay}"/>
            </DataGrid.Columns>
          </DataGrid>
        </DataTemplate>
        <DataTemplate x:Key="BetParamView">
          <DataGrid AutoGenerateColumns="False" HeadersVisibility="None" ItemsSource="{Binding Path=FilterBBets}" CanUserDeleteRows="False" >
            <DataGrid.Columns>
              <DataGridCheckBoxColumn Binding="{Binding Path=active}"/>
              <DataGridTextColumn Binding="{Binding Path=result}" IsReadOnly="True"/>
              <DataGridTextColumn Binding="{Binding Path=brate}" IsReadOnly="True"/>
            </DataGrid.Columns>
          </DataGrid>
        </DataTemplate>
    


    В момент создания класса Bet происходит перехват событий и вывод на экран соответствующих сообщений. Когда же я начинаю редактировать таблицу, никаких сообщений не появляется. Соответственно, отследить наличие изменений не возможно.

     

    Относительно статьи в журнале. Я попытался аналогично сделать, но эффекта не получил. То есть, фильтрованная коллекция не изменялась.

     

    Единственное решение, которое я придумал и оно помогло, было следующим:

    ListCollectionView _FilterBBets;
    public ListCollectionView FilterBBets 
    { 
       get 
       {
         _FilterBBets.Refresh();
         return _FilterBBets; 
       }
       private set 
       {
         _FilterBBets = value;
         OnPropertyChanged("FilterBBets");
       }
     }
    


    В этом случае, коллекция обновлялась и результаты редактирования BBetsList корректно отображались.

    Хотелось бы всё таки выяснить, почему не сработал никак первый вариант.

    • Помечено в качестве ответа Sergey Rogachev 19 июля 2011 г. 12:36
    14 июля 2011 г. 8:35