我正在尝试制作一个WPF应用程序。应用程序需要使用"列表视图"来显示对数据库的查询结果。我已经能够成功地创建应用程序(GUI、数据库、LINQ等),但是,我的查询结果的显示看起来更像"网格"。
下面项目的规范显示,结果中出现的每个记录旁边都需要有一个绿色圆圈图标。我已经从下面的图像中删除了实际结果,以保持数据库的内容私有。
我没有足够的信誉点来发布图片,所以我发布了图片作为我使用的示例/测试域。你可以在这里看到WPF应用程序的屏幕截图和代码:
http://digitalworkzone.com/WPF.html
我做错了什么?我是否需要在代码中添加或修改一些内容,以便能够获得绿色圆圈和更多的"列表"样式来显示我的查询结果?
了解WPF内容模型。http://msdn.microsoft.com/en-us/library/bb613548.aspx
任何具有"Content"属性的东西基本上都有两种行为。如果"Content"设置为从UIElement
派生的内容,则该类将管理自己的表示。然而,其他任何东西都只会调用.ToString()
,而是显示文本。
从长远来看,这意味着WPF中的所有内容都可以显示任何内容。如果你想在按钮中显示一个按钮,你可以。例如:
<Button>
<Button.Content>
<Button Content="This will show as text" />
</Button.Content>
</Button>
内部按钮将有文本,但外部按钮将显示Button
,因为Button
源自UIElement
,因此将处理自己的演示。
在上面的图片示例中,您有想要用图形信息填充的ListBox
es/DataGrid
s。试试这个:
<ListBox HorizontalContentAlignment="Stretch">
<ListBox.Items>
<Button Content="One"/>
<Button Content="Two"/>
<Button Content="Three"/>
<Button Content="Four"/>
</ListBox.Items>
</ListBox>
现在您有一个ListBox,它显示Buttons
而不是Text。您可以更进一步,将项目包含在堆叠面板中,例如:
<ListBox HorizontalContentAlignment="Stretch">
<ListBox.Items>
<StackPanel Orientation="Horizontal">
<Button Content="A button"/>
<Label Content="Some text" />
</StackPanel>
<StackPanel Orientation="Horizontal">
<Button Content="A button"/>
<Label Content="Some text" />
</StackPanel>
<StackPanel Orientation="Horizontal">
<Button Content="A button"/>
<Label Content="Some text" />
</StackPanel>
</ListBox.Items>
</ListBox>
现在我们有了包含布局容器(StackPanels
,然后它包含其他元素)的项。
但是,如果在其他位置设置ItemsSource
,则实际上可以使用DataTemplate
来显示内容。DataTemplate
实际上是以一个特定类为目标,并按照XAML中的定义对其内容进行布局。考虑:
代码隐藏:
public partial class MyWindow : UserControl {
public MyWindow() {
InitializeComponent();
MyListBox.ItemsSource = new List<Person> {
new Person("Sam", "Smith"),
new Person("Jim", "Henson"),
new Person("Betty", "White"),
};
}
XAML:
<ListBox HorizontalContentAlignment="Stretch" x:Name="MyListBox" >
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" >
<Label Content="{Binding FirstName}"/>
<Label Content="{Binding LastName}"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
现在,当Listbox显示时,它将遍历ItemsSource
属性中的每个项,然后使用DataTemplate对它们进行布局。如果您使用多态性(例如在不同类型的人中,如"Cusomters"或"Employees",它们都源自"Person
"),则可以通过使用DataType
属性来获得DataTemplate
目标特定类。
这种方法的问题是直接设置项的值,这是不好的形式。最好定义一个单独处理视图所有数据的类。考虑:
public class ViewModel {
// WPF will automatically read these properties using reflection.
public List<Person> People {
get {
return new List<Person> {
new Person("Sam", "Smith"),
new Person("Jim", "Henson"),
new Person("Betty", "White")
};
}
}
}
它将保存视图的所有数据,现在让我们将其添加到实际窗口中。首先,我们需要引用名称空间("xmlns"表示xml名称空间):
<Window x:Class="Sharp.MyWindow"
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"
xmlns:lol="clr-namespace:Sharp">
名称空间是Sharp
(我的东西所在的名称空间),我们给它的别名是lol
。现在,我们通过将ViewModel
类设置为DataContext
属性将其附加到窗口,如所示
<Window>
<Window.DataContext>
<lol:ViewModel />
</Window.DataContext>
</Window>
这使得ViewModel
类上的所有公共属性都可用于Window
。这样,如果我们想将Persons
信息读取到我们的ListBox
中,我们只需说:
<ListBox HorizontalContentAlignment="Stretch" ItemsSource="{Binding People}" >
...
</ListBox>
请注意,我们说的是ItemsSource={Binding People}
,意思是"扫描ViewModel
中名为"People"的任何公共属性,然后检索这些结果。"。这基本上是MVVM方法背后的基础。您可能将所有业务逻辑都放在一个或多个类中,这些类处理Model
中的主应用程序操作,但您也有一个ViewModel
,它与Model
交互并将结果公开为公共属性。WPF会自动绑定到这些属性,并将它们呈现给您。信息只是流动,而不是强行设置值。
要真正理解WPF应该如何工作,您应该花一些时间来理解MVVM的基础知识。WPF的设计确实考虑到了MVVM,所以要真正了解WPF的工作原理,你真的应该花点时间来了解它http://agilewarrior.wordpress.com/2011/01/11/simple-mvvm-walkthrough-part-i/。
<ListBox ItemsSource="{Binding QueryResults}">
<ListBox.ItemsTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Image Source="{Binding ImageSource}"/>
<TextBlock Text="{Binding TextSource}"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemsTemplate>
</ListBox>
如果您的代码后面有一个名为QueryResults
的对象列表,则会起作用。每个对象都需要具有名为ImageSource
的字符串属性和名为TextSource
的字符串属性。
但是,由于只需要为每个项目显示一个绿色圆圈图标,因此可以对图像源进行硬编码。不过,如果你想为每一个都有一个不同的图标,上面的内容就会起作用。
还要注意,为了使其工作,您需要将窗口的DataContext
设置为DataContext="{Binding RelativeSource={RelativeSource Self}}"