Member 11774405 Ответов: 2

Как я могу получить неоплаченные счета в месяц в datagridview?


я новый ученик .net, и я пытаюсь получить неоплаченные месяцы счетов в datagridview2 из datagridview1.

предположим, что счета одного человека там основаны на месяцах, например с января по октябрь как оплаченные месяцы и Ноябрь ,Декабрь как неоплаченные месяцы.

поэтому, когда я ищу имя клиента, то datagridview1 отображается с января по октябрь как оплаченные месяцы, но как получить имя двух других неоплаченных месяцев в datagridview2 ??

используя запрос я могу получить оплаченные месяцы из базы данных для datagridview1 и для datagridview2,

здесь у меня есть добавить 12 месяцев сначала как строка типа,

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, который будет извлекать новые строки, такие как ноябрь и декабрь.

как я могу получить оставшиеся два месяца в datagridview2??

Что я уже пробовал:

используя запрос я могу получить оплаченные месяцы из базы данных для datagridview1 и для datagridview2,

здесь у меня есть добавить 12 месяцев сначала как строка типа,

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, который будет извлекать новые строки, такие как ноябрь и декабрь.

MadMyche

Лучше всего было бы хранить все учетные данные ( счета и платежи ) в базе данных и использовать их для заполнения таблиц данных. Как еще вы могли бы отслеживать, что оплачивается, а что нет?

Member 11774405

используя цикл может быть мы можем выбрать последний месяц счета как оплаченный из первого datagridview и остаться счет месяцев как неоплаченный можно добавить во второй datagridview

2 Ответов

Рейтинг:
1

Graeme_Grant

При работе с WPF проще сначала сделать данные с помощью Привязка данных (WPF)[^]. Таким образом, представление и данные разделяются, давая окно в данные. Преимущество заключается в том, что вы разделяете данные, а затем можете выбрать, как эти данные будут восприниматься пользователем.

Джон отчасти прав, тот самый Шаблон проектирования MVVM[^] лучше поможет отделить данные от представления. Это решение будет использовать MVVM, однако существует гораздо более эффективный метод WPF, встроенный в .Net Framework, чтобы делать то, что вы хотите.

При работе с коллекциями данных, а фильтрация, сортировка и т. д. используются на коллекциях в памяти, лучшим методом WPF является использование Классу collectionviewsource[^] и привязать к результирующему представлению ваши данные.

Ниже приведен пример того, как использовать CollectionViewSource с DataGrid и ComboBox чтобы выбрать тип фильтра.

Во-первых, нам нужно реализовать обертки для INotifyPropertyChanged Интерфейс[^] используется для передачи изменений в привязке данных.

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;
}

Далее нам нужен класс для хранения данных экземпляра для каждого элемента в нашей коллекции:
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);
    }
}

Теперь мы можем создать нашу модель представления, используемую для привязки данных к представлению:
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 = $"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();
    }
}

Теперь мы можем наконец реализовать нашу точку зрения:
<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 изменится примененный фильтр и результаты DataGrid повторит примененный фильтр.

Примечание: в RefreshFilter() из MainViewModel Я использую локальные функции для предварительного определения фильтра, а не помещаю полный фильтр в PeopleView.Filter Как и любой циклический код, поместите как можно меньше внутри цикла, чтобы максимизировать производительность.

Здесь должно быть достаточно информации, чтобы применить ее к вашему собственному проекту для реализации того типа фильтрации, которого вы хотите достичь.


Рейтинг:
0

#realJSOP

Вам не нужно делать две выборки данных. Вы должны использовать MVVM 5 для достижения того, что вы хотите.

0) создайте объект модели, который отвечает за получение данных из базы данных (или другого источника данных).

1) Создайте объект viewmodel, который принимает ваш объект модели и добавляет свойства, отражающие желаемую бизнес-модель, что сделает его более легким/удобным для работы в пользовательском интерфейсе. В этом случае вы захотите иметь ObservableCollection объекта item, реализующего INotifyProperyChanged таким образом, любые изменения, внесенные в коллекцию, будут немедленно отражены в пользовательском интерфейсе.

2) Создайте конвертер, который возвращает Visible, или Collapsed, основываясь на том, что gridview передает ему, так что один вид сетки будет показывать "оплаченные" объекты, а другой - "неоплаченные" объекты.

Это правильный способ сделать то, что вы хотите в WPF.