【问题标题】:Dynamic Collapse-Panel creation in Windows Forms / C#在 Windows 窗体/C# 中创建动态折叠面板
【发布时间】:2013-10-31 17:33:42
【问题描述】:

我需要编写一个 Windows 窗体,用户可以在其中查看按“客户”分组的许多“合同”。每个客户必须是一个展开-折叠面板,并且客户的合同必须在相应的面板内。

我已经尝试了很棒的ExpandCollapsePanel,但是当客户数量很大时,即使将 AutoScroll 属性设置为 true,面板也不会自动滚动.

有人知道其他的选择吗?请记住,面板必须是动态创建的,因为有很多客户,并且每个客户都有很多合同。

谢谢!

【问题讨论】:

  • 在使用winforms的时候,你应该尽量保持你的UI简单,如果有要求,你应该考虑一些支持丰富控件集的第三方UI库。复杂的UI只建议你用WPF,自定义自己复杂的控件很痛苦,也有bug,我在一个项目中经历过这样的痛苦,很难忘记。
  • 同意@KingKing,您可以通过简单的ListBox 在WPF 中实现这一点,同时保持UI Virtualization 处理任何数量的数据而不会损失性能,而在winforms 中尝试类似的东西会像地狱一样。
  • 我明白了你的意思,@HighCore 发送的这段视频展示了 WPF 在性能方面优于 WinForms。以前从未使用过WPF :(
  • @wind39 this video 说明了为什么 WPF 确实优于 .Net Windows 应用程序的 winforms。如果您在现有的 winforms 项目中工作,并且需要引入复杂(丰富)的 UI 功能,您可以使用ElementHostForm 或面板中托管 WPF 内容。让我知道这是否适合您,我可以提供一些示例代码。
  • @HighCore 很棒的视频!我不知道ElementHost,它真的很适合我们的应用程序。如果您提供一些示例代码,我会很高兴,谢谢!

标签: c# winforms panel collapse expand


【解决方案1】:

好的,我创建了一个示例,使用 ElementHost 来托管 WPF UserControl,它看起来像这样:

我已经上传了完整的源代码Here,但无论如何这些都是最相关的部分:

表格1:

public partial class Form1 : Form
{
    public CustomerContractsViewModel ContractsVM { get; set; }

    public Form1()
    {
        InitializeComponent();

        ContractsVM  = new CustomerContractsViewModel();

        var customercontractsview = new CustomerContractsView(){DataContext = ContractsVM};

        var elementHost = new ElementHost() { Dock = DockStyle.Fill };
        elementHost.Child = customercontractsview;

        panel1.Controls.Add(elementHost);
    }

    private void button1_Click(object sender, EventArgs e)
    {
        ContractsVM.LoadCustomers(DataSource.GetCustomers());
    }
}

(为简洁起见,省略了设计器代码)

WPF 视图:

<UserControl x:Class="ElementHostSamples.CustomerContractsView"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300">
    <UserControl.Resources>
        <!-- This style is applied to all Label elements within the UserControl-->
        <Style TargetType="Label">
            <Setter Property="FontWeight" Value="Bold"/>
            <Setter Property="HorizontalAlignment" Value="Right"/>
        </Style>

        <!-- This DataTemplate will be used to render the Contract items-->
        <DataTemplate x:Key="ContractTemplate">
            <Grid>
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto"/>
                    <RowDefinition Height="Auto"/>
                </Grid.RowDefinitions>

                <Grid.ColumnDefinitions>
                    <ColumnDefinition/>
                    <ColumnDefinition/>
                </Grid.ColumnDefinitions>

                <Label Grid.Row="0" Grid.Column="0" Content="Contract Date:"/>
                <Label Grid.Row="1" Grid.Column="0" Content="Amount:"/>

                <TextBlock Grid.Row="0" Grid.Column="1" Text="{Binding ContractDate, StringFormat='MM/dd/yyyy'}" VerticalAlignment="Center"/>
                <TextBlock Grid.Row="1" Grid.Column="1" Text="{Binding Amount, StringFormat=C}" VerticalAlignment="Center"/>
            </Grid>
        </DataTemplate>

        <!-- This DataTemplate will be used to render the Customer Items -->
        <DataTemplate x:Key="CustomerTemplate">
            <Expander Header="{Binding Name}">
                <ListBox ItemsSource="{Binding Contracts}" ItemTemplate="{StaticResource ContractTemplate}">
                    <ListBox.Template>
                        <ControlTemplate TargetType="ListBox">
                            <ItemsPresenter/>
                        </ControlTemplate>
                    </ListBox.Template>
                </ListBox>
            </Expander>
        </DataTemplate>
    </UserControl.Resources>

    <ListBox ItemsSource="{Binding Customers}"
             ItemTemplate="{StaticResource CustomerTemplate}"/>
</UserControl>

代码背后:

public partial class CustomerContractsView : UserControl
{
    public CustomerContractsView()
    {
        InitializeComponent();
    }
}

视图模型:

public class CustomerContractsViewModel:PropertyChangedBase
{
    public List<Customer> Customers { get; set; }

    public void LoadCustomers(List<Customer> customers)
    {
        Customers = customers;
        OnPropertyChanged("Customers");
    }
}
    1234563调用”(不管那是什么意思)或背后可怕的庞大代码。并且不会强迫您在 DevExpress 或 Telerik 等第三方组件上花费大量资金。这就是为什么 WPF 是所有 .Net Windows 桌面应用程序开发的最佳选择,无论它是不是简单的 Hello World 类型的东西。
  • 我使用ItemsControl 来托管Customer 项目,在这些项目中我使用带有自定义DataTemplate 的列表框来显示Contract 项目。

  • ItemsControl(外部和内部)都是Virtualized,即使有 200,000 个项目,也可以立即响应。

  • 请注意,没有一行代码与 UserControls 的 UI 元素交互,一切都在 XAML 中定义,并通过 DataBinding 填充数据。这使得大量的可扩展性和可维护性成为可能,因为 UI 与应用程序逻辑/业务逻辑完全解耦。这就是 WPF 的方式。

  • Form代码(初始化代码除外)只与ViewModel交互,无需与WPF View交互。

  • 从 winforms 升级到 WPF 时,您非常需要接受 The WPF Mentality,也就是说,如前所述,您几乎从不在过程代码中操作 UI 元素,或者使用过多隐藏代码,而是对所有内容都使用 DataBinding 并接受 The MVVM Pattern

  • WPF 摇滚。下载链接的源代码并亲自查看结果。

  • 如果您需要进一步的帮助,请告诉我。

【讨论】:

  • WPF 和你都摇滚,@HighCore!我该如何表达我的感激之情?您解决了我们的问题:1)在几分钟内; 2)最好的方法; 3)最快的方式; 4) 具有干净、直观、可维护的代码; 5) 具有高质量的文档,让我相信为什么 WPF 优于 WinForms。最重要的是,现在我将学习这项技术并在其他情况下使用它。非常感谢!
猜你喜欢
  • 2014-06-25
  • 2020-08-04
  • 2012-01-27
  • 2013-11-04
  • 2012-07-09
  • 1970-01-01
  • 2016-09-22
  • 2010-11-21
  • 1970-01-01
相关资源
最近更新 更多