I have an ItemTemplateSelector that uses the typical C# code for logic, but that code never even gets called from my ItemsControl. Right now I have just stubbed in ONE of the Selector Display Templates for "StringTemplate" and I have those in my "Parameters" array, yet it never calls selector.
<Grid>
<ItemsControl ItemsSource="{Binding Parameters}">
<ItemsControl.Resources>
<local:ReportRun_LaunchView_ParameterTemplateSelector x:Key="TemplateSelector_FormDetails">
<local:ReportRun_LaunchView_ParameterTemplateSelector.StringTemplate>
<DataTemplate>
<fv:WatermarkTextBox
Grid.Row="1"
Grid.Column="0"
Margin="0,0,7,0"
fv:WpfMvmFocusManager.FocusKey="txtSearchNpi"
Text="{fv:OnChangedBinding Path=StringValue}"
WatermarkContent="{Binding DataContext.Name}" />
</DataTemplate>
</local:ReportRun_LaunchView_ParameterTemplateSelector.StringTemplate>
</local:ReportRun_LaunchView_ParameterTemplateSelector>
</ItemsControl.Resources>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel
HorizontalAlignment="Stretch"
IsItemsHost="True"
Orientation="Horizontal" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<ItemsControl x:Name="items" ItemTemplateSelector="{StaticResource TemplateSelector_FormDetails}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
Related
i am working on state machine test design tool, but i am facing issue with dragging and drop the added nodes in the design panel. Since these nodes are added in the run-time. i can not implement the drag drop event for each added node , knowing that i am using WPF with caliburn.micro platform and MVVM
XAML code
<!-- Column 2 : Design panel-->
<StackPanel x:Name="DesignPanelState" Grid.Row="1" Grid.Column="2" Grid.RowSpan="2" >
<ItemsControl x:Name="Nodes" MouseLeftButtonDown="Nodes_MouseLeftButtonDown">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border BorderBrush="Black" BorderThickness="1" Margin ="3" Padding="3">
<StackPanel Orientation="Vertical" MouseMove="Nodes_MouseMove">
<Button x:Name="NodeIdx" Content="{Binding NodeName}" MinWidth="50" MinHeight="50"/>
</StackPanel>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
Image of UI
I found the answer of my question in https://www.codeproject.com/Articles/15354/Dragging-Elements-in-a-Canvas
I integrated class DragCanvas.cs into my project and included following line in the header of the XAML file
xmlns:jas="clr-namespace:WPF.JoshSmith.Controls"
and XAML code became
<!-- Column 2 : Design panel-->
<jas:DragCanvas x:Name="DesignPanelState"
Grid.Column="2" Grid.RowSpan="3"
AllowDragging="{Binding ElementName=Move, Path=IsChecked}"
AllowDragOutOfView="False">
<ItemsControl x:Name="Nodes">
<ItemsControl.ItemsPanel >
<ItemsPanelTemplate >
<Canvas AllowDrop="True"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate >
<DataTemplate>
<Button x:Name="NodeIdx" BorderBrush="Aquamarine" BorderThickness="1" Content="{Binding NodeName}" MinWidth="50" MinHeight="50"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</jas:DragCanvas>
How can I bind a delegate command to a dynamically added UserControl button?
I have my UserControl button
<ItemsControl
ItemsSource="{Binding SomeCollection}"
HorizontalAlignment="Center">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid
Columns="2" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<DMX_ControlLibrary:DMX_ItemBox
Width="250"
Height="150"
FontSize="12"
Command="{Binding ItemBoxButtonCommand}"
Content="{Binding Path=.}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
And in my view model, I have this
private ICommand itemBoxButtonCommand;
public ICommand ItemBoxButtonCommand
{
get { return (this.itemBoxButtonCommand) ?? (this.itemBoxButtonCommand = new DelegateCommand(ItemButton_Click)); }
}
private void ItemButton_Click()
{
MessageBox.Show("");
}
Binding doesn't seem to work this way unlike it does on statically added controls.
How can I make it work?
As you stated in the comments for ItemBoxButtonCommand:
It's in the viewmodel that contains SomeCollection!
When the data template is applied for each item in the SomeCollection, each DMX_ItemBox will get its DataContext set the the corresponding item, not the data context of the ItemsControl which contains the SomeCollection.
In order to bind to the ItemBoxButtonCommand, you can use a RelativeSource binding to the DataContext of the ItemsControl (which is a parent of the items).
<ItemsControl.ItemTemplate>
<DataTemplate>
<DMX_ControlLibrary:DMX_ItemBox
Width="250"
Height="150"
FontSize="12"
Command="{Binding DataContext.ItemBoxButtonCommand, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"
Content="{Binding Path=.}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
Alternatively, assign an x:Name to the ItemControl and refer to it with ElementName.
<ItemsControl
x:Name="MyItemsControl"
ItemsSource="{Binding SomeCollection}"
HorizontalAlignment="Center">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid
Columns="2" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<DMX_ControlLibrary:DMX_ItemBox
Width="250"
Height="150"
FontSize="12"
Command="{Binding DataContext.ItemBoxButtonCommand, ElementName=MyItemsControl}"
Content="{Binding Path=.}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
I am implementing User Controls in my application with MVVM structure. How can I bind different User Controls in a single page and show in a window screen.
Like below image. I want same as it is in the image.
ViewModel code
public RelayCommand OpenWidgetList => new RelayCommand(() =>
{
ControlList = new List<UserControl>();
ControlList.Add(ObjColumn1L);
ControlList.Add(ObjColumn1L);
ControlList.Add(ObjColumn1M);
ControlList.Add(ObjColumn1S);
ControlList.Add(ObjColumn1XL);
ControlList.Add(ObjColumn1XXL);
ControlList.Add(ObjColumn2L);
ControlList.Add(ObjColumn2M);
ControlList.Add(ObjColumn2S);
ControlList.Add(ObjColumn2XL);
ControlList.Add(ObjColumn2XXL);
ControlList.Add(ObjColumn3L);
ControlList.Add(ObjColumn3M);
ControlList.Add(ObjColumn3S);
ControlList.Add(ObjColumn4M);
ControlList.Add(ObjColumn4S);
}, true);
XAML Code
<UniformGrid Name="widgetData" Background="Black" VerticalAlignment="Top" Height="691" Margin="0,50,0,0">
<UniformGrid Columns="3">
<UniformGrid Rows="6">
<UniformGrid>
<ItemsControl ItemsSource="{Binding ControlList}" Name="UserControlColumn" Margin="4,0" >
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel HorizontalAlignment="Left" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<controls:UserControlColumn HorizontalAlignment="Left" Margin="2" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</UniformGrid>
</UniformGrid>
</UniformGrid>
</UniformGrid>
</Grid>
Yes, I found answer.
By coding I tried much but can not do that but in a simple way I had done by XAML side. Nothing but copy the code and separately bind each user Control with only one data from the back-end in DataCollection variable. Without binding each User Control from the back-end codes.
Below are my XAML code of WPF file. where repetedly done for each User Control to bind in the form.
<UniformGrid Rows="1">
<ItemsControl ItemsSource="{Binding DataCollection}" Name="UserControlColumn1" Margin="4,0">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel HorizontalAlignment="Left" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<controls:UserControlColumn1 HorizontalAlignment="Left" Margin="2" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</UniformGrid>
<UniformGrid Rows="1">
<ItemsControl ItemsSource="{Binding DataCollection}" Name="UserControlColumn2" Margin="4,0">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel HorizontalAlignment="Left" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<controls:UserControlColumn2 HorizontalAlignment="Left" Margin="2" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</UniformGrid>
<!--Same for other user Controls as above two...-->
Every user control has its own datacontext so in your main viewmodel you add a property for every usercontrol viewmodel and then you bind it. Something like this:
UserControl1ViewModel
{
....
}
MainViewModel
{
UserControl1ViewModel UserControl1ViewModel {get; private set;}
}
I am working on c# xaml using silverlight and i am bit confused about the hierarchy of this xaml code:
<UserControl.Resources>
<this:MyValueConverter x:Key="TabConverter"/>
</UserControl.Resources>
<Grid x:Name="LayoutRoot" Background="Green">
<ItemsControl ItemsSource="{Binding Path=TabList, Mode=OneWay}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas></Canvas>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border Width="150" Background="red" Height="100" Canvas.Left="{Binding TabList, Mode=TwoWay, Converter={StaticResource TabConverter}}" Canvas.Top="100" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
When i run it gives a big green color window(sorry if technical names are not correct), whereas it should also show red color somewhere in same window as it has Border Width="150" Background="red" .Could some one please explain me what this code is doing ?
ItemsControl really just binds to a list and applies a datatemplate (border with background red) for each item in the list. As for the reason you're only seeing green, well there's probably nothing in the TabList property on your viewmodel. That way, nothing in the items template renders, and all you see is green.
You'll need to make sure that TabList is bound correctly (it exists on your datacontext, whether that's a view model or not) and that it has items in it.
Here's a simpler version of what you may want to accomplish:
<Grid x:Name="LayoutRoot" Background="Green">
<ItemsControl ItemsSource="{Binding Path=TabList, Mode=OneWay}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border Width="150" Background="red" Height="100" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
I have two user controls, WorkflowTileItemsControl and WorkflowTileControl. The WorkflowTileItemsControl hosts the WorkflowTileControl in an ItemsControl. However, there are dependency properties on the WorkflowTileControl that I would like to expose to anything using the WorkflowTileItemsControl. In order to do that here is ItemsControl code for WorkflowTileItemsControl.
<ItemsControl ItemsSource="{Binding Source={StaticResource WorkflowTilesViewSource}}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<ContentPresenter Content="{Binding WorkflowTileControl, ElementName=ctrlWorkflowTileItems}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
However this doesn't seem to work. It is only showing the last item in the ItemsControl. Below is code that works, and is the functionality I'm looking for (minus hard coding all the dependency properties).
<ItemsControl ItemsSource="{Binding Source={StaticResource WorkflowTilesViewSource}}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<OrderCommon:WorkflowTileControl IsReadOnly="True" Margin="5" TasksTitle="Defects" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
And this is what my calling code looks like.
<OrderCommon:WorkflowTileItemsControl WorkflowRequirementTypeCode="DISBURSEMENTDFCT" Margin="5" MinWidth="1000" MaxWidth="1250" HorizontalAlignment="Left">
<OrderCommon:WorkflowTileItemsControl.WorkflowTileControl>
<OrderCommon:WorkflowTileControl IsReadOnly="True" Margin="5" TasksTitle="Defects" />
</OrderCommon:WorkflowTileItemsControl.WorkflowTileControl>
</OrderCommon:WorkflowTileItemsControl>
I feel like there is some simple step I'm missing. I'm not sure if ContentPresenter is the right tool for the job. I haven't done anything like this in WPF before. Can someone please assist?
So after some days of research I've found a solution. The WorkflowTileItemsControl needs to expose a Dependency Property of a DataTemplate which will be bound to the ItemsTemplate for the ItemsControl. Here is the xaml for the WorkflowTileItemsControl:
<ItemsControl ItemsSource="{Binding Source={StaticResource WorkflowTilesViewSource}}" ItemTemplate="{Binding WorkflowTileTemplate, ElementName=ctrlWorkflowTileItems}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
And Here is the xaml for the calling control:
<OrderCommon:WorkflowTileItemsControl WorkflowRequirementTypeCode="DISBURSEMENTDFCT" Margin="5" Width="1130" HorizontalAlignment="Left">
<OrderCommon:WorkflowTileItemsControl.WorkflowTileTemplate>
<DataTemplate>
<OrderCommon:WorkflowTileControl IsReadOnly="True" Margin="5" TasksTitle="Defects" />
</DataTemplate>
</OrderCommon:WorkflowTileItemsControl.WorkflowTileTemplate>
</OrderCommon:WorkflowTileItemsControl>