c# - 使用 MVVM 模式将项目添加到数据绑定(bind)列表框的最佳方法?

标签 c# wpf xaml mvvm

我目前在我的 WPF 项目中遇到问题。此时我有一个 Viewmodel,它有一个 Manager(与 repo 通信)。

internal class TicketViewModel
{
    private TicketManager mgr;

    public IEnumerable<Ticket> List { get; set; }


    public TicketViewModel()
    {
        mgr = new TicketManager();
        List = mgr.GetTickets();

    }

}

我已经设法将此列表绑定(bind)到我的主窗口中的列表框。下一步是我需要在列表中添加一张额外的票,并将其传递给经理。问题是我需要主窗口中某些控件的两个参数。从 MVVM 的角度来看,我需要使用绑定(bind)命令,例如一个与 View 模型通信的按钮,因为我的 View 模型不能/可能无法访问窗口中的控件。使用参数化命令是否可以到达这里?

下一个问题是我猜 Listbox 不会更新。这是代码:
<ListBox x:Name="listboxTix" BorderThickness="0" ItemsSource="{Binding List}">
    <ListBox.ItemTemplate>
        <DataTemplate>
            <Border BorderBrush="Bisque" Background="Beige" BorderThickness="2">
                <StackPanel Width="250">
                    <TextBlock Text="{Binding TicketNumber}" />
                    <TextBlock Text="{Binding Text}" />
                    <TextBlock Text="{Binding State}" />
            </StackPanel>
            </Border>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

我发现使用 CompareableCollection 是去这里的方法,但是在添加新票后我仍然需要再次阅读所有票。

提前致谢,
喜喜

最佳答案

好的,这里是代码。

假设您在 MainWindow 上有三个文本框(因为您有三个文本 block 。)所以您的 MainWindow.xaml 好像

<Window.DataContext>
    <local:MyViewModel/>--set's your viewModel
</Window.DataContext>

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="250*"/>
        <RowDefinition Height="90"/>
        <RowDefinition Height="30"/>
    </Grid.RowDefinitions>
    <ListBox Grid.Row="0" x:Name="listboxTix" BorderThickness="0" ItemsSource="{Binding List}">
        <ListBox.ItemTemplate>
            <DataTemplate>
                <Border BorderBrush="Bisque" Background="Beige" BorderThickness="2">
                    <StackPanel Width="250">
                        <TextBlock Text="{Binding TicketNumber}" />
                        <TextBlock Text="{Binding Text}" />
                        <TextBlock Text="{Binding State}" />
                    </StackPanel>
                </Border>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>
    <TextBox x:Name="TicketNumber" Grid.Row="1" TextWrapping="Wrap" Text="{Binding Path=Text}" VerticalAlignment="Top" Width="120"/>
    <TextBox x:Name="Text" Grid.Row="1" TextWrapping="Wrap" Text="{Binding Path=State}" />
    <TextBox x:Name="State" Grid.Row="1" TextWrapping="Wrap" Text="{Binding Path=TicketNumber}" />
    <Button Content="Button" Command="{Binding Path=MainCommand}"  Grid.Row="2"/>

</Grid>

我假设你有一些名为 class 的类门票 其中包含这三个成员
Class Ticket
{
    public int TicketNumber { get; set; }
    public string Text { get; set; }
    public string State { get; set; }
}

现在上课票务经理 我们用一些虚拟数据填充它
 class TicketManager
{
    ObservableCollection<Ticket> tl = new ObservableCollection<Ticket>();
    internal ObservableCollection<Ticket> GetTickets()
    {
        tl.Add(new Ticket() { State = "State1", Text = "Text1", TicketNumber = 1 });
        tl.Add(new Ticket() { State = "State2", Text = "Text2", TicketNumber = 2 });
        tl.Add(new Ticket() { State = "State3", Text = "Text3", TicketNumber = 3 });

        return tl;
    }

}

在您的主窗口 ViewModel 中,我们将其称为 MyViewModel.cs 我们增加
class MyViewModel:INotifyPropertyChanged
{
    private TicketManager mgr;
    public ObservableCollection<Ticket> List { get; set; }

    private string text;
    private string state;
    private int ticketNumber;

    private readonly DelegateCommand<object> MyButtonCommand;
    public Class1()
    {
        mgr = new TicketManager();
        List = mgr.GetTickets();
        MyButtonCommand = new DelegateCommand<object>((s) => { AddListToGrid(text, state, ticketNumber); }, (s) => { return !string.IsNullOrEmpty(text) && !string.IsNullOrEmpty(state); });

    }

    private void AddListToGrid(string text, string state, int ticketNumber)
    {
        List.Add(new Ticket() {Text=text,State=state,TicketNumber=ticketNumber });
    }

    public DelegateCommand<object> MainCommand
    {
        get
        {
            return MyButtonCommand;
        }
    }

    public string Text
    {
        get
        {
            return text;
        }
        set
        {
            text = value;
            OnPropertyChanged("Text");
            MyButtonCommand.RaiseCanExecuteChanged();
        }
    }

    public string State
    {
        get
        {
            return state;
        }
        set
        {
            state = value;
            OnPropertyChanged("State");
            MyButtonCommand.RaiseCanExecuteChanged();
        }
    }

    public int TicketNumber
    {
        get
        {
            return ticketNumber;
        }
        set
        {
            ticketNumber = value;
            OnPropertyChanged("TicketNumber");
            MyButtonCommand.RaiseCanExecuteChanged();
        }
    }

    private void OnPropertyChanged(string p)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(p));
    }


    public event PropertyChangedEventHandler PropertyChanged;
}

您可以随意修改代码

这个 ViewModel 实现了一些从 MVVM 角度来看非常重要的东西

1) INotifyPropertyChanged

2) WPF Delegate Command

P.S:代码经过测试,按预期运行

关于c# - 使用 MVVM 模式将项目添加到数据绑定(bind)列表框的最佳方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28918007/

相关文章:

c# - 下拉列表中的图像

c# - Windows 7 有时无法检测到 HDMI 电视?可以在代码中调用 Detect 吗?

c# - 获取所有打开的 WPF 窗口

c# - WPF-对话框相对源绑定(bind)(MVVM)

c# - 使用带有 Caliburn micro Message.Attach 的附加事件

silverlight - 如何在 Windows Phone 8 上将数据与常量字符串绑定(bind)

c# - "App.Current.myProperty"不起作用,但 "((app)Application.Current).myProperty"起作用

c# - 如何在不丢失强类型的情况下返回代码优先 Entity Framework 中的 DbGeography.Distance 计算值?

wpf - MouseEnter 事件可以/应该冒泡吗?

c# - WPF,如何在选择后重置组合框