我需要编写一个 Windows 窗体,用户可以在其中查看按“客户”分组的许多“合同”。每个客户必须是一个展开-折叠面板,并且客户的合同必须在相应面板内。
我已经尝试过很棒的ExpandCollapsePanel ,但是当客户数量很大时,即使AutoScroll属性设置为true,面板也不会自动滚动。
有人知道其他替代品吗?请记住,面板必须是动态创建的,因为有许多客户和属于每个客户的许多合同。
谢谢!
好的,我创建了一个使用ElementHost
托管 WPF的示例UserControl
,它看起来像这样:
我已经在这里上传了完整的源代码,但无论如何这些是最相关的部分:
表格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");
}
}
请注意这个简单的、不到 100 行代码、20 分钟的 WPF 示例比您希望在 winforms 中实现的任何东西都要好,并且不需要任何“所有者绘制”、“P/Invoke”(无论这意味着什么) ) 或可怕的庞大代码背后的东西。并且不会强迫您在 DevExpress 或 Telerik 等第三方组件上花费大量资金。这就是为什么 WPF 是所有 .Net Windows 桌面应用程序开发的最佳选择,无论它是否是简单的 Hello World 类型的东西。
我使用ItemsControl来托管Customer
项目,在这些项目中,我使用带有自定义DataTemplate的 ListBox来显示Contract
项目。
ItemsControl(外部和内部)都经过虚拟化,即使有 200,000 个项目,也能立即响应。
请注意,没有一行代码与 UserControls 的 UI 元素交互,一切都在 XAML 中定义并通过DataBinding填充数据。由于 UI 与应用程序逻辑/业务逻辑完全解耦,因此可以实现大量的可扩展性和可维护性。这就是 WPF 的方式。
Form
代码(初始化代码除外)只与 . 交互,ViewModel
无需与 WPF View 交互。
从 winforms 升级到 WPF 时,你真的需要拥抱WPF Mentality,也就是如前所述,你几乎从不在过程代码中操作 UI 元素,或者使用过多的代码,而是使用 DataBinding 处理一切并拥抱MVVM图案
WPF 摇滚。下载链接的源代码并亲自查看结果。