Usercontrol as datatemplate with bindings

I have an ItemsControl with ItemsSource binded to a list of SystemModels. It has to generate an usercontrol for every system in the list. And in those usercontrols it has some textboxes that show the name, is and location of the system.

My code creates the usercontrols but doesn't fill the textboxes in the usercontrol.

View:

<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>

ViewModel:

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");
    } 
}

multilinebutton code:

        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); }
    }

what not works: partID="{Binding ID}", company="{Binding ItemsSource.Company}", typeSorter="{Binding ItemsSource.Name, ElementName=SystemList}", typeLocation="{Binding ItemsSource.Location, ElementName=SystemList}" and buttonCommandParameter="{Binding ItemsSource.ID, ElementName=SystemList}".

But if i use just a button as datatemplate with Content="{Binding ID}" It works Perfect, an d if i use the usercontrol outside the datatemplate it works also. But it will not work inside the datatemplate.

The error i get is this: "BindingExpression path error: 'Company' property not found on 'object' ''MultiLineButton' (Name='')'. BindingExpression:Path=Company; DataItem='MultiLineButton' (Name=''); target element is 'MultiLineButton' (Name=''); target property is 'company' (type 'String')"

How can i fix those bindings?


  • not sure, maybe you should remove DataType="SystemModel" from DateTemplate.
  • Or try to use simple textbox(Binding id) as DataTemplate, see if there is still empty.
  • If above didn't get you any help, try Snoop(snoopwpf.codeplex.com) see what happended.

  • try 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);
        }
    }
    

    and xaml should be:

    <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>
    

    As chao wang said:

    remove DataType="SystemModel" because if you're using just one type of DataType as DataTemplate it's not necessary. and the correct syntax is DataType="vm:SystemModel" where vm is defined in a parent tag like : xmlns:vm="clr-namespace:MySolution.MyVmProject.MyFolder"

    also check these:

    remove ItemsSource. from Bindings inside DataTemplate because it's just wrong.

    double check all names in bindings because if they're wrong null value is considered during runtime and you never know.

    check your dataContext make sure UserControl have its DataContext to the correct instance of type dependency object which have Systems in it. and make sure it's remains that way.

    链接地址: http://www.djcxy.com/p/44612.html

    上一篇: WPF如何评估一个属性进行绑定

    下一篇: Usercontrol as datatemplate with bindings