如何在datagridview中获取未付账单? [英] How can I fetch unpaid bills month in datagridview?

查看:112
本文介绍了如何在datagridview中获取未付账单?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是新的.net学习者,我正在尝试从datagridview1获取datagridview2中的未付帐单月。



假设,一个人账单是基于几个月,比如1月到10月作为付费月份和11月,12月作为无薪月份。



所以当我搜索客户名称时,datagridview1会在1月到10月显示为付费月份但是如何在datagridview2中获取其他两个未付费的月份名称?



使用查询我可以从数据库中获取有关数据的数据,同时获取datagridview1和datagridview2,



这里我首先添加12个月的字符串,



i am new .net learner and i am trying to fetch unpaid bill months in datagridview2 from datagridview1.

suppose, one person bills are there based on months, like January to October as paid months and November ,December both as unpaid months.

so when i search name of customer then datagridview1 is displayed January to October as paid months but How to other two unpaid months name fetch in datagridview2 ??

using query i am able to fetch paid months from database for datagridview1 and for datagridview2,

here i have add 12 month first as string like,

Dim i As Integer
        Dim month(12) As String
        month(0) = "January"
        month(1) = "February"
        month(2) = "March"
        month(3) = "April"
        month(4) = "May"
        month(5) = "June"
        month(6) = "July"
        month(7) = "August"
        month(8) = "September"
        month(9) = "October"
        month(10) = "November"
        month(11) = "December"



然后



为datagridview2创建一个列,它可以获取11月和12月的新行。



我如何获取保留两个月在datagridview2 ??



我尝试过:



使用查询我可以从datagridview1和datagridview2的数据库中获取付费月份,



这里我先添加12个月像字符串一样,




and then

create a column for datagridview2, which is fetch the new rows like November and December.

how can i fetch remain two months in datagridview2??

What I have tried:

using query i am able to fetch paid months from database for datagridview1 and for datagridview2,

here i have add 12 month first as string like,

Dim i As Integer
        Dim month(12) As String
        month(0) = "January"
        month(1) = "February"
        month(2) = "March"
        month(3) = "April"
        month(4) = "May"
        month(5) = "June"
        month(6) = "July"
        month(7) = "August"
        month(8) = "September"
        month(9) = "October"
        month(10) = "November"
        month(11) = "December"



然后



为。创建一列datagridview2,它获取像11月和12月这样的新行。


and then

create a column for datagridview2, which is fetch the new rows like November and December.

推荐答案

您不需要进行两次数据提取。您应该使用MVVM 5来完成您想要的任务。



0)创建一个负责从数据库(或其他数据源)获取数据的模型对象。 />


1)创建一个viewmodel对象,它接受您的模型对象,并添加反映所需业务模型的属性,以便在UI中更轻松/更方便地使用它。在这种情况下,您将需要一个实现 INotifyProperyChanged 的项目对象的 ObservableCollection ,以便对所做的任何更改该集合将立即反映在用户界面中。



2)创建返回可见或<$的转换器c $ c>折叠,基于gridview传递给它的内容,这样一个网格视图将显示付费对象,另一个将显示未付对象。



这是在WPF中做你想做的事情的正确方法。
You don't need to do two data fetches. You should use MVVM 5to accomplish what you want.

0) Create a model object that is responsible for getting data from the database (or other data source).

1) Create a viewmodel object that takes your model object, and adds properties that reflect the desired business model that will make it easier/more convenient to work with in the UI. In this case, you'll want to have an ObservableCollection of an item object that implements INotifyProperyChanged so any changes made to the collection will be immediately reflected in the UI.

2) Create converter that returns Visible, or Collapsed, based on what the gridview passes to it, so that one grid view will show "paid" objects, and the other will display "unpaid" objects.

That's the RIGHT way to do what you want in WPF.


使用WPF时,首先通过数据绑定(WPF) [ ^ ]。这样,视图和数据就会分开,从而为数据提供一个窗口。好处是您要分离数据,然后您可以选择用户如何看到这些数据。



John部分正确, MVVM设计模式 [ ^ ]将更好地帮助将数据与视图分开。这个解决方案将使用MVVM,但是.Net Framework中内置了一个更高效的WPF技术来实现你想要的功能。



使用数据集时,内存集合中使用过滤,排序等,最好的WPF方法是使用 CollectionViewSource [ ^ ]并将生成的视图绑定到您的数据中。



下面是一个如何使用 CollectionViewSource DataGrid 以及 ComboBox 选择过滤器类型。



首先,我们需要为INotifyPropertyChanged Interfa ce [ ^ ]用于在DataBinding中传递更改。

When working with WPF, it is easier to do data first via Data Binding (WPF)[^]. This way the view and data are separated giving a window into the data. The benefit is that you're separating the data, and you can then choose how that data is seen by the user.

John is partially correct, the MVVM Design Pattern[^] will better help separate the data from the view. This solution will use MVVM, however there is a far more efficient WPF technique built into the .Net Framework to do what you want.

When working with Collections of data, and filtering, sorting, etc is used on in-memory collections, the best WPF method is to use the CollectionViewSource[^] and bind to the resulting view into you data.

Below is a sample of how to use the CollectionViewSource with the DataGrid and a ComboBox to select the filter type.

First, we need to implement wrappers for the INotifyPropertyChanged Interface[^] used to communicating changes in DataBinding.
public abstract class ObservableBase : INotifyPropertyChanged
{
    public void Set<TValue>(ref TValue field, TValue newValue, [CallerMemberName] string propertyName = "")
    {
        if (!EqualityComparer<TValue>.Default.Equals(field, default(TValue)) && field.Equals(newValue)) return;

        field = newValue;
        RaisePropertyChanged(propertyName);
    }

    public void RaisePropertyChanged (string propertyName)
        => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));

    public event PropertyChangedEventHandler PropertyChanged;
}

public abstract class ViewModelBase : ObservableBase
{
    public bool IsInDesignMode
        => (bool) DesignerProperties.IsInDesignModeProperty
            .GetMetadata(typeof(DependencyObject))
            .DefaultValue;
}



接下来我们需要一个类来保存我们集合中每个项目的实例数据:


Next we need a class to hold instance data for each item in our collection:

public class PersonModel : ObservableBase
{
    private string name;
    public string Name
    {
        get => name;
        set => Set(ref name, value);
    }

    private decimal paid;
    public decimal Paid
    {
        get => paid;
        set => Set(ref paid, value);
    }

    private decimal owing;
    public decimal Owing
    {
        get => owing;
        set => Set(ref owing, value);
    }
}



现在我们可以创建用于将数据绑定到视图的ViewModel:


Now we can create our ViewModel used to bind the data to the view:

class MainViewModel : ViewModelBase
{
    public MainViewModel() => Mock();

    private Random rand = new Random();

    public ObservableCollection<PersonModel> People { get; }
        = new ObservableCollection<PersonModel>();

    private CollectionViewSource CSV { get; set; }
    public ICollectionView PeopleView { get; private set; }

    public List<string> PaymentStates { get; }
        = new List<string> {"All", "Not Paid", "Partially Paid", "Paid in Full"};

    private string selectedState;
    public string SelectedState
    {
        get => selectedState;
        set
        {
            Set(ref selectedState, value);
            RefreshFilter();
        }
    }

    private void Mock()
    {
        for (int i = 0; i < 500; i++)
        {
            var owed = rand.Next(100, 500);
            var paidState = rand.Next(1, 100);

            People.Add(new PersonModel
            {
                Name =


人{i}
欠款=欠款,
付款= paidState > 0 &&" paidState < 33
0
:paidState > 32 && paidState < 66
?rand.Next( 5 ,欠/ / span class =code-digit> 10 )* 10
:欠
});
}

selectedState = PaymentStates [ 0 ];

CSV = new CollectionViewSource {Source = People};
PeopleView = CSV.View;

RefreshFilter();
}

private void RefreshFilter()
{
Func< PersonModel,bool>过滤式;

switch (PaymentStates.IndexOf(selectedState))
{
案例 1 // 未付款
filterType = x = > x.Paid == 0 ;
break ;
case 2 // 部分支付
filterType = x = > x.Paid > 0 && x.Paid < x.Owing;
break ;
case 3 // 全额付款
filterType = x = > x.Paid > = x.Owing;
break ;
默认
filterType = _ = > ;
break ;
}

PeopleView.Filter = item = > filterType(item as PersonModel);

// 基于过滤器的更新
PeopleView.Refresh( );
}
}
"Person {i}", Owing = owed, Paid = paidState > 0 && paidState < 33 ? 0 : paidState > 32 && paidState < 66 ? rand.Next(5, owed / 10) * 10 : owed }); } selectedState = PaymentStates[0]; CSV = new CollectionViewSource {Source = People}; PeopleView = CSV.View; RefreshFilter(); } private void RefreshFilter() { Func<PersonModel, bool> filterType; switch (PaymentStates.IndexOf(selectedState)) { case 1: // not paid filterType = x => x.Paid == 0; break; case 2: // partially paid filterType = x => x.Paid > 0 && x.Paid < x.Owing; break; case 3: // paid in full filterType = x => x.Paid >= x.Owing; break; default: filterType = _ => true; break; } PeopleView.Filter = item => filterType(item as PersonModel); // update based on filter PeopleView.Refresh(); } }



现在我们终于可以实现我们的视图:


Now we can finally implement our View:

<Window x:Class="FilteredDataGrid.MainWindow"

        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

        xmlns:local="clr-namespace:FilteredDataGrid"

        Title="MainWindow" Height="450" Width="800">
    <Window.DataContext>
        <local:MainViewModel/>
    </Window.DataContext>
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <TextBlock Text="Raw Data"/>
        <DataGrid Grid.Row="1"

                  ItemsSource="{Binding People}"/>
        <StackPanel Grid.Column="1" 

                    Orientation="Horizontal">
            <Label Content="Filter By:"/>
            <ComboBox ItemsSource="{Binding PaymentStates}"

                      SelectedItem="{Binding SelectedState}"

                      Width="100" Margin="10 0 0 0"/>
        </StackPanel>
        <DataGrid Grid.Row="1" Grid.Column="1"

                  x:Name="FilterResults"

                  ItemsSource="{Binding PeopleView}"/>
    </Grid>
</Window>



更改 Combobox 中的选项将change the filter applied and the results DataGrid will relect the applied filter.



Note: in the <$c $c>RefreshFilter() of the MainViewModel I'm using local functions to predefine the filter and not putting the complete filter in the <$c $c>PeopleView.Filter. Like any looping code, put as little inside the loop as possible to maximise the performance.



There should be enough information here to apply to your own project to implement the type of filtering that you want to achieve.


Changing the selection in the Combobox will change the filter applied and the results DataGrid will relect the applied filter.

Note: in the RefreshFilter() of the MainViewModel I'm using local functions to predefine the filter and not putting the complete filter in the PeopleView.Filter. Like any looping code, put as little inside the loop as possible to maximise the performance.

There should be enough information here to apply to your own project to implement the type of filtering that you want to achieve.


这篇关于如何在datagridview中获取未付账单?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆