使用Usercontrol作为DataTemplate并绑定数据

3
我是一名有用的助手,可以为您翻译文本。

我有一个ItemsControl,其ItemsSource绑定到SystemModels列表。它必须为列表中的每个系统生成一个用户控件。在这些用户控件中,有一些文本框显示系统的名称、ID和位置。

我的代码创建了用户控件,但没有填充用户控件中的文本框。

视图:

<UserControl x:Name="SystemListScreen">
        <ScrollViewer Grid.Row="1">
                <ItemsControl x:Name="SystemList" ItemsSource="{Binding Path=Systems}">
                    <ItemsControl.ItemsPanel>
                        <ItemsPanelTemplate>
                            <UniformGrid Columns="4"/>
                        </ItemsPanelTemplate>
                    </ItemsControl.ItemsPanel>
                    <ItemsControl.ItemTemplate>
                        <DataTemplate DataType="SystemModel">
                        <Widgets:MultiLineButton partID="{Binding ID}"
                                                    company="{Binding ItemsSource.Company}"
                                                    typeSorter="{Binding ItemsSource.Name, ElementName=SystemList}"
                                                    typeLocation="{Binding ItemsSource.Location, ElementName=SystemList}"
                                                    buttonCommand="{Binding DataContext.navigateInspectList, ElementName=SystemListScreen}"
                                                    buttonCommandParameter="{Binding ItemsSource.ID, ElementName=SystemList}"/>
                        <!--<Button Content="{Binding ID}"/>-->
                    </DataTemplate>
                    </ItemsControl.ItemTemplate>
                </ItemsControl>
        </ScrollViewer>
</UserControl>

视图模型:

private List<SystemModel> systems;

public SystemListViewModel()
{
    Systems = new List<SystemModel>();
    Systems = SystemAPI.Instance.GetSystems();
}

public string App { get; set; }

public List<SystemModel> Systems 
{ 
    get { return systems; }
    private set 
    {
        systems = value;
        NotifyChanged("systems");
        NotifyChanged("NoResultsFound");
    } 
}

多行按钮代码:

        public static readonly DependencyProperty buttonCommandProperty = DependencyProperty.Register("buttonCommand", typeof(ICommand), typeof(MultiLineButton));
    public static readonly DependencyProperty buttonCommandParameterProperty = DependencyProperty.Register("buttonCommandParameter", typeof(Object), typeof(MultiLineButton));
    public static readonly DependencyProperty partIDProperty = DependencyProperty.Register("partID", typeof(String), typeof(MultiLineButton));
    public static readonly DependencyProperty companyProperty = DependencyProperty.Register("company", typeof(String), typeof(MultiLineButton));
    public static readonly DependencyProperty typeSorterProperty = DependencyProperty.Register("typeSorter", typeof(String), typeof(MultiLineButton));
    public static readonly DependencyProperty typeLocationProperty = DependencyProperty.Register("typeLocation", typeof(String), typeof(MultiLineButton));

    public MultiLineButton()
    { 
        this.DataContext = this;

        InitializeComponent();
    }

    public String partID
    {
        get { return (String)GetValue(partIDProperty); }
        set { SetValue(partIDProperty, value); }
    }

    public String company
    {
        get { return (String)GetValue(companyProperty); }
        set { SetValue(companyProperty, value); }
    }

    public String typeSorter
    {
        get { return (String)GetValue(typeSorterProperty); }
        set { SetValue(typeSorterProperty, value); }
    }

    public String typeLocation
    {
        get { return (String)GetValue(typeLocationProperty); }
        set { SetValue(typeLocationProperty, value); }
    }

    public ICommand buttonCommand
    {
        get { return (ICommand)GetValue(buttonCommandProperty); }
        set { SetValue(buttonCommandProperty, value); }
    }
    public Object buttonCommandParameter
    {
        get { return (Object)GetValue(buttonCommandParameterProperty); }
        set { SetValue(buttonCommandParameterProperty, value); }
    }

不起作用的部分是:partID="{Binding ID}", company="{Binding ItemsSource.Company}", typeSorter="{Binding ItemsSource.Name, ElementName=SystemList}", typeLocation="{Binding ItemsSource.Location, ElementName=SystemList}",以及 buttonCommandParameter="{Binding ItemsSource.ID, ElementName=SystemList}"。
但如果我只使用一个带有 Content="{Binding ID}" 的按钮作为数据模板,它可以正常工作。如果我在数据模板之外使用用户控件,它也可以正常工作。但是,在数据模板内部将不起作用。
我收到的错误是:“BindingExpression 路径错误:'Company' 属性在 'object' ''MultiLineButton' (Name='')' 上未找到。BindingExpression:Path=Company;DataItem='MultiLineButton' (Name='');target element 是'MultiLineButton'(Name='');target property 是'company'(type 'String')”。
如何修复这些绑定?

1
从绑定中删除“ItemsSource.”。数据上下文已经设置为ItemsSource。 - Bizhan
1
NotifyChanged("systems"); 是区分大小写的,而 NotifyChanged("Systems") 则不同。 - eran otzap
感谢Bizz和Eran的帮助,但是两位都没有解决问题。 - user2499088
2个回答

2
尝试使用ObservableCollection:
private ObservableCollection<SystemModel> _systems = new ObservableCollection<SystemModel>();
public ObservableCollection<SystemModel> Systems { get { return _systems; } }

public SystemListViewModel()
{
    var systems = SystemAPI.Instance.GetSystems();
    foreach (var system in systems)
    {
        Systems.Add(system);
    }
}

而XAML应该是:

<UserControl x:Name="SystemListScreen">
        <ScrollViewer Grid.Row="1">
                <ItemsControl x:Name="SystemList" ItemsSource="{Binding Path=Systems}">
                    <ItemsControl.ItemsPanel>
                        <ItemsPanelTemplate>
                            <UniformGrid Columns="4"/>
                        </ItemsPanelTemplate>
                    </ItemsControl.ItemsPanel>
                    <ItemsControl.ItemTemplate>
                        <DataTemplate>
                            <Widgets:MultiLineButton 
                                partID="{Binding ID}"
                                company="{Binding Company}"
                                typeSorter="{Binding Name}"
                                typeLocation="{Binding Location}"
                                buttonCommand="{Binding DataContext.navigateInspectList, 
                                    ElementName=SystemListScreen}"
                                buttonCommandParameter="{Binding ItemsSource.ID, 
                                    ElementName=SystemList}"/>
                        </DataTemplate>
                    </ItemsControl.ItemTemplate>
                </ItemsControl>
        </ScrollViewer>
</UserControl>

如chao wang所说:
如果您只使用一种DataType作为DataTemplate,则不需要移除DataType="SystemModel"。正确的语法是DataType="vm:SystemModel",其中vm在父标记中定义,如:xmlns:vm="clr-namespace:MySolution.MyVmProject.MyFolder" 此外,请检查以下内容:
DataTemplate内的绑定中删除ItemsSource。,因为这是错误的。
仔细检查绑定中的所有名称,因为如果它们错误,则在运行时将被视为null值,而您永远不知道。
检查您的dataContext,确保UserControl将其DataContext设置为具有Systems类型的依赖对象的正确实例,并确保它保持这种方式。

尝试为ID、公司、位置和名称定义依赖属性。 - Bizhan
你们所说的定义依赖属性是什么意思?partID等都是依赖属性。 - user2499088
我以为你正在使用INotifyPropertyChanged与普通对象。在我看来,你错过了很多东西,这是因为它变得复杂了。 - Bizhan
而 SystemModel 也有这些依赖属性吗? - Bizhan
多行按钮是用户控件还是自定义控件? - Bizhan
显示剩余3条评论

2
  1. 不确定,也许您应该从DateTemplate中删除DataType="SystemModel"
  2. 或者尝试使用简单的文本框(绑定id)作为DataTemplate,看看是否仍然为空。
  3. 如果上述方法都没有帮助,请尝试使用Snoop(snoopwpf.codeplex.com)查看发生了什么。

1
  1. 尝试过了,但是不起作用。
  2. 这个可以工作,问题在于用户控件没有绑定到列表项。
- user2499088

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接