我怎样才能制作一个“手风琴小部件”?在 WPF 中?
目标:
我试图在 WPF 中实现类似的目标:
(来源:wordpress.org)
初步解决方案:
目前,我尝试将 ItemsControl
与由 Expander< 组成的
ItemTemplate
结合使用/代码>。
我希望 Expander
的 Header
部分具有一致的外观,但我希望 Expander
的 Content
部分完全灵活。因此,它基本上是一组垂直堆叠的“portlet”,其中每个 portlet 都有一致的标题栏,但内容不同。
到目前为止的代码:
这是我目前所拥有的:
<ItemsControl
Grid.Row="2"
Grid.Column="2">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Expander>
<Expander.HeaderTemplate>
<DataTemplate>
<StackPanel
Orientation="Horizontal">
<TextBlock
FontSize="14"
FontWeight="Bold"
Text="Title_Of_Expander_Goes_Here" />
<TextBlock
Margin="10,0,0,0"
FontWeight="Bold"
FontSize="18"
Text="*" />
</StackPanel>
</DataTemplate>
</Expander.HeaderTemplate>
<Expander.Template>
<ControlTemplate
TargetType="Expander">
<Border
BorderThickness="1">
<ContentPresenter />
</Border>
</ControlTemplate>
</Expander.Template>
</Expander>
</DataTemplate>
</ItemsControl.ItemTemplate>
<ItemsControl.Items>
<StackPanel>
<TextBlock
FontSize="14"
FontWeight="Bold"
Text="Users:" />
<wt:DataGrid
Margin="0,1,0,0"
AutoGenerateColumns="False"
CanUserAddRows="True"
CanUserDeleteRows="True"
ItemsSource="{Binding Source={StaticResource Main_SystemUsers}, XPath=//Users/*}">
<wt:DataGrid.Columns>
<wt:DataGridTextColumn
Header="User Name"
Binding="{Binding XPath=@UserName}" />
<wt:DataGridComboBoxColumn
Header="Role"
ItemsSource="{Binding Source={StaticResource Main_UserRoles}, XPath=//Roles/*}"
SelectedValueBinding="{Binding XPath=@Role}" />
</wt:DataGrid.Columns>
</wt:DataGrid>
<StackPanel
Margin="0,10,0,0"
Orientation="Horizontal">
<Button
Content="Add New User..." />
<Button
Margin="10,0,0,0"
Content="Delete User..." />
</StackPanel>
</StackPanel>
</ItemsControl.Items>
</ItemsControl>
讨论:
当我运行此代码时,唯一显示的是DataGrid
用户及其下方的按钮(“添加新用户”和“删除用户”)。没有 Expander
或标题栏。另外,即使我确实看到了一个,我也不知道如何为标题栏上显示的标题设置 Binding
。如果我使用 ItemsSource
,我知道如何进行绑定,但我想以声明方式设置我的项目。
问题:
我应该如何解决这个问题?我正在寻找现有的解决方案或干净的解决方案。
编辑:
我最终做的是用 StackPanel
替换 ItemsControl
并为我的扩展器编写一个样式。事实证明这要简单得多,而且 ItemsControl
确实没有任何好处,因为无论如何我都需要为每个项目声明自定义内容。剩下的一个问题是如何为每个扩展器实现自定义标题。这就是 @Thomas Levesque 建议使用 TemplateBinding
的地方。我所要做的就是将我的标头模板中的 Text="Title_Of_Expander_Goes_Here"
替换为 >Text="{TemplateBinding 内容}"
。
The goal:
I'm trying to achieve something like this in WPF:
(source: wordpress.org)
An initial solution:
At the moment, I'm trying to use an ItemsControl
with an ItemTemplate
composed of an Expander
.
I want a consistent look for the Header
portion of the Expander
, but I want the Content
portion of the Expander
to be completely flexible. So, it's basically a set of "portlets" stacked vertically, where each portlet has a consistent title bar but different content.
The code so far:
This is what I have at the moment:
<ItemsControl
Grid.Row="2"
Grid.Column="2">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Expander>
<Expander.HeaderTemplate>
<DataTemplate>
<StackPanel
Orientation="Horizontal">
<TextBlock
FontSize="14"
FontWeight="Bold"
Text="Title_Of_Expander_Goes_Here" />
<TextBlock
Margin="10,0,0,0"
FontWeight="Bold"
FontSize="18"
Text="*" />
</StackPanel>
</DataTemplate>
</Expander.HeaderTemplate>
<Expander.Template>
<ControlTemplate
TargetType="Expander">
<Border
BorderThickness="1">
<ContentPresenter />
</Border>
</ControlTemplate>
</Expander.Template>
</Expander>
</DataTemplate>
</ItemsControl.ItemTemplate>
<ItemsControl.Items>
<StackPanel>
<TextBlock
FontSize="14"
FontWeight="Bold"
Text="Users:" />
<wt:DataGrid
Margin="0,1,0,0"
AutoGenerateColumns="False"
CanUserAddRows="True"
CanUserDeleteRows="True"
ItemsSource="{Binding Source={StaticResource Main_SystemUsers}, XPath=//Users/*}">
<wt:DataGrid.Columns>
<wt:DataGridTextColumn
Header="User Name"
Binding="{Binding XPath=@UserName}" />
<wt:DataGridComboBoxColumn
Header="Role"
ItemsSource="{Binding Source={StaticResource Main_UserRoles}, XPath=//Roles/*}"
SelectedValueBinding="{Binding XPath=@Role}" />
</wt:DataGrid.Columns>
</wt:DataGrid>
<StackPanel
Margin="0,10,0,0"
Orientation="Horizontal">
<Button
Content="Add New User..." />
<Button
Margin="10,0,0,0"
Content="Delete User..." />
</StackPanel>
</StackPanel>
</ItemsControl.Items>
</ItemsControl>
Discussion:
The only thing that shows up when I run this is the DataGrid
of users and the buttons ("Add New User" and "Delete User") below it. There is no Expander
or title bar. Also, even if I did see one, I'm not sure how to set up a Binding
for the title that appears on the title bar. I know how to do bindings if I use ItemsSource
, but I wanted to set my items declaratively.
The question:
How should I go about this? I'm looking for either a fix for what I have now or a clean-sheet solution.
Edit:
What I ended up doing was replacing the ItemsControl
with a StackPanel
and just writing a style for my expanders. This proved to be much simpler, and there really was no benefit to the ItemsControl
since I needed to declare custom content for each item anyway. The one issue remaining was how to achieve a custom title for each expander. That's where @Thomas Levesque's suggestion to use TemplateBinding
came in. All I had to do was replace Text="Title_Of_Expander_Goes_Here"
in my header's template (see code above) with Text="{TemplateBinding Content}"
.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您没有看到 Expander,因为您重新定义了它的模板。这个应该效果更好:
You're not seeing the Expander because you redefined its template. This one should work better :
我个人认为 TreeView 控件将为您提供更好的工作基础,特别是如果您使用 Expression Blend 作为为项目创建新/空白模板的基础。查看默认模板非常有启发性,可以让您进行更细粒度的控制,并更好地理解和洞察默认情况下的工作方式。然后你就可以带着它们进城了。看起来您正在使用分层数据,而 TreeView 本质上非常适合处理此类数据。
Personally I think a TreeView control would give you a much better base to work from, especially if you're using Expression Blend as a basis to create new/blank Templates from for items. Seeing the default Templates is extremely enlightening and gives you much more fine-grained control and better understanding and insight into how things work by default. Then you can go to town on them. It also looks like you're working with Hierchical Data and TreeViews inherently lend themselves well to working with such data.