列表框的编程绑定在 WPF 中不起作用
我有一个用户控件,它以编程方式设置列表框的数据源 (确切地说是 XmlDataProvider 和 DataTemplate)但在运行时它永远不会正确显示。当加载用户控件时。数据提供者的所有设置都没有反映出来。
你能帮我解决这个问题吗? 我对开发 WPF 应用程序非常陌生。
TIA
这是代码:
XAML
<UserControl x:Class="ENGAGIAUCL.Views.ImageViewer"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Height="500" Width="550">
<UserControl.Resources>
<XmlDataProvider x:Key="FormDataProvider"/>
<DataTemplate x:Key="FormTemplate">
<Border Background="#2200FF00"
BorderBrush="Black"
BorderThickness="1"
CornerRadius="8"
Margin="2,4,2,4"
Padding="4">
<StackPanel HorizontalAlignment="Stretch">
<TextBlock Text="{Binding XPath=name}" />
</StackPanel>
</Border>
</DataTemplate>
</UserControl.Resources>
<DockPanel>
<Border DockPanel.Dock="Top"
Height="45">
<TextBlock x:Name="tbkContentTitle"
Text="Content Title Goes Here"
VerticalAlignment="Center"
HorizontalAlignment="Center"
FontSize="20">
</TextBlock>
</Border>
<DockPanel>
<Border DockPanel.Dock="Bottom">
</Border>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="150"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<ListBox x:Name="lbPreview"
IsSynchronizedWithCurrentItem="True"
VerticalAlignment="Top"
Height="455"
Grid.Column="0"
ItemsSource="{Binding}">
</ListBox>
<Frame x:Name="ActualContentFrame"
Grid.Column="1"
Source="{Binding XPath=url}">
</Frame>
</Grid>
</DockPanel>
</DockPanel>
</UserControl>
这是 .cs 文件
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Xml;
using EngagiaCL.CommonObjects;
using EngagiaCL.Functions;
namespace ENGAGIAUCL.Views
{
/// <summary>
/// Interaction logic for ImageViewer.xaml
/// </summary>
public partial class ImageViewer : UserControl
{
public ImageViewer()
{
InitializeComponent();
Loaded += (s, e) =>
{
LoadContents();
};
}
#region Methods
private void LoadContents()
{
if (CurrentUser != null)
{
XmlDataProvider provider = (XmlDataProvider)this.FindResource("FormDataProvider");
DataTemplate template = (DataTemplate)this.FindResource("FormTemplate");
Binding templatebinding = new Binding();
provider.Document = CurrentUser.UserDoc;
provider.XPath = GetResourcePath();
template.DataType = (object)GetDataTemplateObject();
Resources["FormDataProvider"] = provider;
Resources["FormTemplate"] = template;
}
}
private string GetResourcePath()
{
string path = string.Empty;
if (ContentType == "ADMIN")
{
path = "/SyncLoginResponse/AdminForms/AdminForm";
}
else
{
path = "/SyncLoginResponse/Forms/Form";
}
return path;
}
private string GetDataTemplateObject()
{
string templateobject = string.Empty;
if (ContentType == "ADMIN")
{
templateobject = "AdminForm";
}
else
{
templateobject = "Form";
}
return templateobject;
}
#endregion
#region Properties
public UserInformation CurrentUser { get; set; }
public string ContentType { get; set; }
#endregion
}
}
这是供参考的 xml:
</SyncLoginResponse>
<AdminForms>
<AdminForm>
<name>Best Form Ever/html</name>
<url>
http://blahblahblah/
</url>
</AdminForm>
</AdminForms>
</SyncLoginResponse>
需要注意的事项:
- CurrentUser 是一个对象,其中包含 UserDoc 属性中的 xml 文档。
- 我在这个应用程序中所做的大部分内容都是我在谷歌搜索中理解的点点滴滴,所以请耐心等待。
I have a user control that sets programmatically a listbox's data source
(an XmlDataProvider and a DataTemplate to be exact) but during runtime it never properly shows up. When the user control is loaded. All the setup for the dataproviders are not reflecting.
Can you help me with this one?
I'm really new in developing WPF applications.
TIA
Here's the code:
XAML
<UserControl x:Class="ENGAGIAUCL.Views.ImageViewer"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Height="500" Width="550">
<UserControl.Resources>
<XmlDataProvider x:Key="FormDataProvider"/>
<DataTemplate x:Key="FormTemplate">
<Border Background="#2200FF00"
BorderBrush="Black"
BorderThickness="1"
CornerRadius="8"
Margin="2,4,2,4"
Padding="4">
<StackPanel HorizontalAlignment="Stretch">
<TextBlock Text="{Binding XPath=name}" />
</StackPanel>
</Border>
</DataTemplate>
</UserControl.Resources>
<DockPanel>
<Border DockPanel.Dock="Top"
Height="45">
<TextBlock x:Name="tbkContentTitle"
Text="Content Title Goes Here"
VerticalAlignment="Center"
HorizontalAlignment="Center"
FontSize="20">
</TextBlock>
</Border>
<DockPanel>
<Border DockPanel.Dock="Bottom">
</Border>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="150"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<ListBox x:Name="lbPreview"
IsSynchronizedWithCurrentItem="True"
VerticalAlignment="Top"
Height="455"
Grid.Column="0"
ItemsSource="{Binding}">
</ListBox>
<Frame x:Name="ActualContentFrame"
Grid.Column="1"
Source="{Binding XPath=url}">
</Frame>
</Grid>
</DockPanel>
</DockPanel>
</UserControl>
And here is the .cs file
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Xml;
using EngagiaCL.CommonObjects;
using EngagiaCL.Functions;
namespace ENGAGIAUCL.Views
{
/// <summary>
/// Interaction logic for ImageViewer.xaml
/// </summary>
public partial class ImageViewer : UserControl
{
public ImageViewer()
{
InitializeComponent();
Loaded += (s, e) =>
{
LoadContents();
};
}
#region Methods
private void LoadContents()
{
if (CurrentUser != null)
{
XmlDataProvider provider = (XmlDataProvider)this.FindResource("FormDataProvider");
DataTemplate template = (DataTemplate)this.FindResource("FormTemplate");
Binding templatebinding = new Binding();
provider.Document = CurrentUser.UserDoc;
provider.XPath = GetResourcePath();
template.DataType = (object)GetDataTemplateObject();
Resources["FormDataProvider"] = provider;
Resources["FormTemplate"] = template;
}
}
private string GetResourcePath()
{
string path = string.Empty;
if (ContentType == "ADMIN")
{
path = "/SyncLoginResponse/AdminForms/AdminForm";
}
else
{
path = "/SyncLoginResponse/Forms/Form";
}
return path;
}
private string GetDataTemplateObject()
{
string templateobject = string.Empty;
if (ContentType == "ADMIN")
{
templateobject = "AdminForm";
}
else
{
templateobject = "Form";
}
return templateobject;
}
#endregion
#region Properties
public UserInformation CurrentUser { get; set; }
public string ContentType { get; set; }
#endregion
}
}
And here's the xml for reference:
</SyncLoginResponse>
<AdminForms>
<AdminForm>
<name>Best Form Ever/html</name>
<url>
http://blahblahblah/
</url>
</AdminForm>
</AdminForms>
</SyncLoginResponse>
Things to note:
- CurrentUser is an object which contains the xml document within the UserDoc property.
- Most of what I did in this application are bits and pieces of what I understood in googling so kindly bear with me.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
老实说,我无法理解您的做法是否是加载 WPF UI 的新编码实践,但很少有事情看起来像是失误...
您的
ListBox.ItemsSource
绑定为{ Binding}
即绑定到整个 View 的DataContext
,但在后面的代码中没有设置 View 或任何更高级别父级的DataContext
操作系统列表框。代码隐藏中的
templateBinding
变量在创建后不会在任何地方使用。为什么要在
LoadContents
方法末尾再次设置FormDataProvider
和FormTemplate
?如果您想“刷新”您的Resources
字典,那么这不是正确的方法。要刷新您的
Resources
,您需要在Resources
字典中删除和添加资源,同时使用DynamicResource
标记引用。让我知道您到底想要实现什么。
Honestly I am unable to understand if yours is a new coding practise for loading a WPF UI, but few things look like a miss...
Your
ListBox.ItemsSource
is bound as{Binding}
i.e. bound to theDataContext
of the entire View, but nowhere in your code behind, have you set theDataContext
of the View or any higher level parent os the ListBox.Your
templateBinding
variable from code behind is not used anywhere after creation.Why are you setting
FormDataProvider
andFormTemplate
again at the end of yourLoadContents
method? If you are wanting to "Refresh" yourResources
dictionary then that is not the correct way.For refreshing your
Resources
you need to remove and add resources in yourResources
dictionary and at the same time useDynamicResource
markup reference.Let me know what is it that you exactly want to achieve.