WPF (IronPython) – Xây dựng Filter trên DataGrid bằng CollectionViewSource

WPF (IronPython) – Xây dựng Filter trên DataGrid bằng CollectionViewSource

Bằng cách sử dụng 1 wrapper trung gian CollectionViewSource, chúng ta có thể dễ dàng xây dựng các chức năng sort, filter, group trên DataGrid Control. Bài viết này sẽ hướng dẫn xây dựng filter cơ bản thông qua ví dụ sau:

Yêu cầu: Có 1 datagrid show ra dữ liệu về sách (tựa sách, số trang). Khi nhập vào textbox phía trên và nhấn button Tìm thì datagrid sẽ được filter tựa sách theo nội dung vừa nhập vào (hình minh họa bên dưới)

clip_image001

Book model:

class Book:
    def __init__(self, title, pageCount):
        self.Title = title
        self.PageCount = pageCount

Viewmodel:

class MyViewModel(BaseModel):
    
    def __init__(self):
        super(MyViewModel, self).__init__()
        self.Books = [
            Book('C++ The Programming Language', 630), 
            Book('C# The Programming Language', 380), 
            Book('Objective-C The Programming Language', 350),
            Book('Beginning Office Calculation', 125),
            Book('Design Pattern', 121),
            Book('Đường lối Đảng', 2000)
            ]
        self._filterValue = ''
        self.FilterValue = 'Program'

    @notify_property
    def FilterValue(self):
        return self._filterValue

    @FilterValue.setter
    def FilterValue(self, value):
        self._filterValue = value
        print 'filtervalue changed to %r' % self.FilterValue

View.CodeBehind:

class MyWindow(Window):
    def __init__(self):
        wpf.LoadComponent(self, 'TestGrid.xaml')
        self.ViewModel = MyViewModel()
        self.DataContext = self.ViewModel
    
    def CollectionViewSource_Filter(self, sender, e):
        book = e.Item
        book.__class__ = Book
        if self.ViewModel.FilterValue.Length < 0:
            e.Accepted = 1
        elif self.ViewModel.FilterValue in book.Title :
            e.Accepted = 1
        else:
            e.Accepted = 0

    def ButtonSearch_Click(self, sender, e):
        CollectionViewSource.GetDefaultView(self.grdBooks.ItemsSource).Refresh();

View.XAML:

<Window 
       xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
       xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
       Title="TestGrid" Height="220" Width="300"> 
    <Window.Resources>
        <CollectionViewSource Source="{Binding Books}" x:Key="cvsBooks" Filter="CollectionViewSource_Filter"/>
    </Window.Resources>
       <StackPanel>
        <StackPanel Orientation="Horizontal" Margin="5">
            <TextBox Width="230" >
                <TextBox.Text>
                    <Binding Path="FilterValue" UpdateSourceTrigger="PropertyChanged" Mode="TwoWay" />
                </TextBox.Text>
            </TextBox>
            <Button Content="Tìm" Width="50" Click="ButtonSearch_Click"/>
        </StackPanel>
           
        <DataGrid Name="grdBooks" ItemsSource="{Binding Source={StaticResource cvsBooks}}" AutoGenerateColumns="False">
            <DataGrid.Columns>
                <DataGridTextColumn Header="Tựa sách" Binding="{Binding Title}" Width="220"/>
                <DataGridTextColumn Header="Số trang" Binding="{Binding PageCount}" Width="*" />
            </DataGrid.Columns>
        </DataGrid>
       </StackPanel>
</Window> 

Cơ chế Observable và lớp cơ sở hỗ trợ Notify Properties

class notify_property(property):

    def __init__(self, getter):
        def newgetter(slf):
            try:
                return getter(slf)
            except AttributeError:
                return None
        super(notify_property, self).__init__(newgetter)

    def setter(self, setter):
        def newsetter(slf, newvalue):
            oldvalue = self.fget(slf)
            if oldvalue != newvalue:
                setter(slf, newvalue)
                slf.OnPropertyChanged(setter.__name__)
        return property(
            fget=self.fget,
            fset=newsetter,
            fdel=self.fdel,
            doc=self.__doc__)
    
    
class BaseModel(INotifyPropertyChanged):
    PropertyChanged = None

    def __init__(self):
        self.PropertyChanged, self._propertyChangedCaller = pyevent.make_event()

    def add_PropertyChanged(self, value):
        self.PropertyChanged += value

    def remove_PropertyChanged(self, value):
        self.PropertyChanged -= value

    def OnPropertyChanged(self, propertyName):
        if self.PropertyChanged is not None:
            self._propertyChangedCaller(self, PropertyChangedEventArgs(propertyName))

Trả lời

Mời bạn điền thông tin vào ô dưới đây hoặc kích vào một biểu tượng để đăng nhập:

WordPress.com Logo

Bạn đang bình luận bằng tài khoản WordPress.com Đăng xuất /  Thay đổi )

Google+ photo

Bạn đang bình luận bằng tài khoản Google+ Đăng xuất /  Thay đổi )

Twitter picture

Bạn đang bình luận bằng tài khoản Twitter Đăng xuất /  Thay đổi )

Facebook photo

Bạn đang bình luận bằng tài khoản Facebook Đăng xuất /  Thay đổi )

Connecting to %s