好的,我创建了一个示例,使用
ElementHost
来托管一个 WPF
UserControl
,它看起来像这样:
![enter image description here](https://istack.dev59.com/p9LPR.webp)
我已经上传了完整的源代码
在这里,但无论如何,以下是最相关的部分:
Form1:
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:
xmlns:x="http:
xmlns:mc="http:
xmlns:d="http:
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="" VerticalAlignment="Center"/>
<TextBlock Grid.Row="1" Grid.Column="1" Text="" VerticalAlignment="Center"/>
</Grid>
</DataTemplate>
<!-- This DataTemplate will be used to render the Customer Items -->
<DataTemplate x:Key="CustomerTemplate">
<Expander Header="">
<ListBox ItemsSource="" ItemTemplate="">
<ListBox.Template>
<ControlTemplate TargetType="ListBox">
<ItemsPresenter/>
</ControlTemplate>
</ListBox.Template>
</ListBox>
</Expander>
</DataTemplate>
</UserControl.Resources>
<ListBox ItemsSource=""
ItemTemplate=""/>
</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中能够实现的任何东西都要好,而且不需要任何“owner draw”、“P/Invoke”(不管那是什么)或者可怕的庞大的代码后台。也不会强迫你花费大量资金购买DevExpress或Telerik等第三方组件。这就是为什么WPF是所有.Net Windows桌面应用程序开发的最佳选择,无论它是一个简单的Hello World类型的东西还是其他。
我正在使用
ItemsControl来托管
Customer
项目,里面我使用了一个带有自定义
DataTemplate的ListBox来显示
Contract
项目。
两个ItemsControl(外部和内部)都是
Virtualized的,以便立即响应时间,即使有20万个项目也是如此。
请注意,没有一行代码与UserControls的UI元素交互,一切都在XAML中定义,并通过
DataBinding填充数据。这使得UI完全脱离应用逻辑/业务逻辑,具有很高的可扩展性和可维护性。这就是WPF的方式。
表单代码(初始化代码除外)只与ViewModel交互,不需要与WPF View交互。
当从winforms升级到WPF时,你需要认真接受
The WPF Mentality,也就是说,如前所述,你几乎
从不在过程代码中操作UI元素或使用过多的代码后台,而是为所有事情使用DataBinding并拥抱
The MVVM Pattern。
WPF很棒。下载链接的源代码并亲自查看结果。
如果需要进一步帮助,请告诉我。
winforms
时,您应该尽可能保持 UI 界面的简单性,如果有必要,可以考虑使用一些支持丰富控件集的第三方 UI 库。只有在使用WPF
时才建议复杂化 UI 界面,自定义复杂控件很麻烦,而且容易出错。我曾经在一个项目中遇到过这样的问题,难以忘怀。 - King KingElementHost
来托管WPF内容到一个Form
或面板中。如果这对您是一个选项,我可以提供一些示例代码。 - Federico Berasategui