【问题标题】:Unable to pass property name dynamically to ListView.ItemTemplate to bind (UWP)无法将属性名称动态传递给 ListView.ItemTemplate 以进行绑定 (UWP)
【发布时间】:2020-05-18 20:54:25
【问题描述】:

我有一个这样的用户控件

<UserControl
x:Class="App41.UserCntrl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d">
<Grid>
    <ListView SelectionMode="Multiple" x:Name="lview"  ItemsSource="{x:Bind ItemsSource, Mode=OneWay}"  >
        <ListView.ItemTemplate>
            <DataTemplate>
                <TextBlock Text="{x:Bind PropertyNameToBind, Mode=OneWay}" />
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>
</Grid>

后面的代码

    public sealed partial class UserCntrl : UserControl
{
    public UserCntrl()
    {
        this.InitializeComponent();
    }
    public static readonly DependencyProperty ItemsSourceProperty =
     DependencyProperty.Register("ItemsSource", typeof(IEnumerable), typeof(UserControl),
         new PropertyMetadata(null));

    public IEnumerable ItemsSource
    {
        get => (IEnumerable)GetValue(ItemsSourceProperty);
        set => SetValue(ItemsSourceProperty, value);
    }

    public string PropertyNameToBind
    {
        get { return (string)GetValue(PropertyNameToBindProperty); }
        set { SetValue(PropertyNameToBindProperty, value); }
    }

    public static readonly DependencyProperty PropertyNameToBindProperty =
    DependencyProperty.Register("PropertyNameToBind", typeof(string), typeof(UserControl), new PropertyMetadata(""));
}

我在我的主页中这样调用这个用户控件

<Page
x:Class="App41.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:App41"  xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"  mc:Ignorable="d">
<Grid>
    <local:UserCntrl x:Name="lview"   Loaded="EditTextControl_Loaded"></local:UserCntrl>
</Grid>

隐藏代码

    public sealed partial class MainPage : Page
{
    public MainPage()
    {
        this.InitializeComponent();
    }

    private void EditTextControl_Loaded(object sender, RoutedEventArgs e)
    {
        ObservableCollection<OptionItem> io = new ObservableCollection<OptionItem>();

        io.Add(new OptionItem { Name = "11111111111" });
        lview.ItemsSource = io;
        lview.PropertyNameToBind = "Name";
    }
}

public class OptionItem 
{
    private string _Name = string.Empty;
    public string Name
    {
        get { return _Name; }
        set { _Name = value;  }
    }
}

对我来说一切都很好,但 ListView 显示的是空项目而不是我的内容。我相信问题出在这一行

  <TextBlock Text="{x:Bind PropertyNameToBind, Mode=OneWay}" />

我试图在OptionItem 模型中绑定Name 属性。我该如何解决这个问题?

【问题讨论】:

    标签: c# xaml uwp uwp-xaml


    【解决方案1】:

    在 UWP 中,每个DataTemplate 对应于ItemsSource 中的一个项目,因此DataTemplateDataContext 仅限于项目本身,特定于您的项目,是OptionItem

    你使用{x:Bind PropertyNameToBind}其实是想绑定OptionItem.PropertyNameToBind,但是你的OptionItem没有这个属性,所以什么都不会显示。

    请确定是要绑定PropertyNameToBind还是OptionItem.Name属性,如果是OptionItem.Name,请使用{x:Bind Name}

    如果没有,试试这个:

    <UserControl
        ...
        x:Name="Main">
    
        <Grid>
            <ListView SelectionMode="Multiple" x:Name="lview"  ItemsSource="{x:Bind ItemsSource, Mode=OneWay}"  >
                <ListView.ItemTemplate>
                    <DataTemplate>
                        <TextBlock Text="{Binding ElementName=Main,Path=PropertyNameToBind}" />
                    </DataTemplate>
                </ListView.ItemTemplate>
            </ListView>
        </Grid>
    </UserControl>
    

    更新

    我想我明白你的意思,但你对绑定有一些误解。

    你绑定的是一个属性,你传递一个字符串值。该值不能作为属性名来反映绑定类的属性。

    结合你的需求,我推荐你使用接口进行动态处理:

    界面

    public interface ITest
    {
        string GetDisplayText();
    }
    

    public class OptionItem : ITest
    {
        public string Name { get; set; } = string.Empty;
        public string GetDisplayText()
        {
            return Name;
        }
    }
    

    控制

    <ListView.ItemTemplate>
        <DataTemplate x:DataType="local:ITest">
            <TextBlock Text="{x:Bind GetDisplayText()}" />
        </DataTemplate>
    </ListView.ItemTemplate>
    

    通过创建界面,提供了一种输出显示文本的方法。

    任何继承这个接口的类都可以根据自己的需要重写这个方法。

    在控件内部,只需要调用GetDisplayText()方法即可,无论绑定哪个类。

    【讨论】:

    • 我希望 PropertyNameToBind 自身被绑定。我尝试了你的解决方案,我的 ListView 仍然是空的
    • 您好,请限制您的ItemsSource的类型,如IEnumerable&lt;OptionItem&gt;。如果问题仍然存在,您可以提供应用程序的目标版本和最低版本。我在1909设备上测试正常。如果您能说出为什么要进行此绑定而不是绑定OptionItem 中的属性,那将会更有帮助。更改OptionItem中的属性时是否要同步修改UI?
    • 我将无法更改ItemsSource类型,这个用户控件需要在整个项目中使用,并且在不同的场景中,我们需要绑定不同类型的IEnumerable。它不会总是 OptionItem。
    • 在这里您可以找到您询问的详细信息,以及我的完整代码filebin.net/t73bczrj2h51cifi
    • 您好,在我回答的代码中,我将 UserControl 命名为 Main,您似乎缺少这个
    【解决方案2】:
     <Grid>
            <ListView SelectionMode="Multiple" x:Name="lview"  ItemsSource="{x:Bind ItemSource, Mode=OneWay}"  >
                <ListView.ItemTemplate>
                    <DataTemplate>
                        <TextBlock Text="{x:Bind OptionItem.Name, Mode=OneWay}" />
                    </DataTemplate>
                </ListView.ItemTemplate>
            </ListView>
        </Grid>
    </Grid>
    

    【讨论】:

    • 我无法在用户控件中硬编码 OptionItem.Name,绑定的值都是动态的,并且来自调用用户控件的页面
    • 我没有关注你在这里尝试做的事情。您有不同的页面,它们都有一个 Listview 控件。这些控件需要绑定到页面上的集合然后显示项目吗?集合是否总是包含相同类型的对象?集合名称是否始终相同?
    • 有一个包含列表视图的用户控件。此用户控件将用于各种页面。在每个页面上,我需要为这个列表视图分配不同的 ItmesSource。每个 ItemsSource 将是不同的类型,但都是 IEnumerable。
    • 在每个页面中,我将分配一个 Itemsource 和一个 PropertyNameToBind。 ItemsSource 包含一个带有多个字段的 Ienumberable,PropertyNameToBind 字符串将决定哪些字段需要绑定到列表视图
    猜你喜欢
    • 2021-11-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-08
    • 2017-11-23
    • 2013-10-08
    相关资源
    最近更新 更多