列表框的编程绑定在 WPF 中不起作用

发布于 2024-12-03 19:27:03 字数 5318 浏览 1 评论 0原文

我有一个用户控件,它以编程方式设置列表框的数据源 (确切地说是 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>

需要注意的事项:

  1. CurrentUser 是一个对象,其中包含 UserDoc 属性中的 xml 文档。
  2. 我在这个应用程序中所做的大部分内容都是我在谷歌搜索中理解的点点滴滴,所以请耐心等待。

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:

  1. CurrentUser is an object which contains the xml document within the UserDoc property.
  2. Most of what I did in this application are bits and pieces of what I understood in googling so kindly bear with me.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

柠檬色的秋千 2024-12-10 19:27:03

老实说,我无法理解您的做法是否是加载 WPF UI 的新编码实践,但很少有事情看起来像是失误...

  1. 您的 ListBox.ItemsSource 绑定为 { Binding} 即绑定到整个 View 的 DataContext,但在后面的代码中没有设置 View 或任何更高级别父级的 DataContext操作系统列表框。

  2. 代码隐藏中的 templateBinding 变量在创建后不会在任何地方使用。

  3. 为什么要在 LoadContents 方法末尾再次设置 FormDataProviderFormTemplate ?如果您想“刷新”您的 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...

  1. Your ListBox.ItemsSource is bound as {Binding} i.e. bound to the DataContext of the entire View, but nowhere in your code behind, have you set the DataContext of the View or any higher level parent os the ListBox.

  2. Your templateBinding variable from code behind is not used anywhere after creation.

  3. Why are you setting FormDataProvider and FormTemplate again at the end of your LoadContents method? If you are wanting to "Refresh" your Resources dictionary then that is not the correct way.

For refreshing your Resources you need to remove and add resources in your Resources dictionary and at the same time use DynamicResource markup reference.

Let me know what is it that you exactly want to achieve.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文