c# - Wpf binding collection property in UserControl (xaml) -
add collections of buttons in usercontrol (options). in xaml disigner displayed.
output when run application:
- if options not initialized, error xamlobjectwriterexception: property collection "wpfappusercontrol.buttons"."options" (null).
- if options = new list(), window without buttons
mainwindow.xaml
<window x:class="wpfappusercontrol.mainwindow" 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" xmlns:local="clr-namespace:wpfappusercontrol" mc:ignorable="d" title="mainwindow" height="250" width="300"> <grid> <local:buttons x:name="buttons" verticalalignment="center" horizontalalignment="center" horizontalcontentalignment="center"> <local:buttons.options> <button content="agudabi 1" height="20" margin="2" /> <button content="agudabi 2" height="20" margin="2" /> <button content="agudabi 3" height="20" margin="2" /> </local:buttons.options> </local:buttons> </grid> </window>
buttons.xaml
<usercontrol x:class="wpfappusercontrol.buttons" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:local="clr-namespace:wpfappusercontrol" mc:ignorable="d" d:designheight="300" d:designwidth="300"> <grid> <wrappanel x:name="internalcontainer" orientation="horizontal" horizontalalignment="center"/> </grid> </usercontrol>
buttons.xaml.cs
#region usings using system.collections.generic; using system.collections.objectmodel; using system.componentmodel; using system.windows; using system.windows.controls; #endregion namespace wpfappusercontrol { public partial class buttons : usercontrol { public buttons() { //options = new observablecollection<button>(); initializecomponent(); } public observablecollection<button> options { { return (observablecollection<button>) getvalue(optionsproperty); } set { setvalue(optionsproperty, value); } } public static readonly dependencyproperty optionsproperty = dependencyproperty.register(nameof(options), typeof(observablecollection<button>), typeof(buttons), new propertymetadata(/*new observablecollection<button>()*/, propertychangedcallback)); private static void propertychangedcallback(dependencyobject d, dependencypropertychangedeventargs e) { var obj = d buttons; foreach (var button in obj.options) { obj.internalcontainer.children.add(button); } } } }
here example of should do.
instead of usercontrol collection property, use itemscontrol this:
<itemscontrol itemssource="{binding options}"> <itemscontrol.itemspanel> <itemspaneltemplate> <wrappanel/> </itemspaneltemplate> </itemscontrol.itemspanel> <itemscontrol.itemtemplate> <datatemplate> <button content="{binding name}" command="{binding command}" height="20" margin="2"/> </datatemplate> </itemscontrol.itemtemplate> </itemscontrol>
then create view model collection of data items properties button content , command:
public class viewmodel { public observablecollection<option> options { get; } = new observablecollection<option>(); } public class option { public string name { get; set; } public icommand command { get; set; } }
initialize shown below, icommand implementation ommited brevity. search web relaycommand implementation details.
public mainwindow() { initializecomponent(); var vm = new viewmodel(); vm.options.add(new option { name = "agudabi 1" }); vm.options.add(new option { name = "agudabi 2" }); vm.options.add(new option { name = "agudabi 3" }); datacontext = vm; }
Comments
Post a Comment