I'm trying to name and then set a DataContext for a ComboBox that's embedded within an ItemsControl.
In my main Window, I can access the ItemsControl by name but not any of the elements within the ItemsControl.
public MainWindow()
{
InitializeComponent();
SList.DataContext = App.SCList; //this is valid
StS.DataContext = App.STList; //this is not
}
And here's the XAML code. I can access SList from within the program but not "StS" or "SPanel1". The compiler error is:
"The name 'StS' does not exist in the current context"
Note that I've tried both "Name" and "x:Name"
<ScrollViewer VerticalScrollBarVisibility="Auto" >
<ItemsControl Name ="SList" ItemsSource ="{Binding}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Margin="12"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border BorderBrush="Black" BorderThickness="3" CornerRadius="5" Margin="8,8" ClipToBounds="True" Background="Beige">
<StackPanel Name="SPanel1">
<StackPanel Orientation="Horizontal">
<Label Content="S Type"/>
<ComboBox Name ="StS" ItemsSource="{Binding Path=ShipType.TypeName, Mode=TwoWay}" DataContext="STList">
</ComboBox>
</StackPanel>
<StackPanel Orientation="Horizontal">
<Label Content="Class Name"/>
<TextBox Text="{Binding Path = Name, Mode=TwoWay}" HorizontalAlignment="Center" FontWeight="Bold" />
</StackPanel>
</StackPanel>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
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 have created some buttons by first filling a class containing get/set methods and then using that info in XAML.
C#
List<MediaDetail> movies = new List<MediaDetail>();
...
...
MovieListView.ItemsSource = movies;
XAML
<Window.Resources>
<DataTemplate x:Key="ItemTemplate">
<WrapPanel Orientation="Vertical" Width="Auto">
<Button Width="200" Height="300" Click="SelectMovie_Click" Name ="NEED THIS TO BE DYNAMIC">
<Button.Template>
<ControlTemplate>
<Image Source="{Binding image}"/>
</ControlTemplate>
</Button.Template>
</Button>
<TextBlock Text="{Binding title}" HorizontalAlignment="Center"/>
</WrapPanel>
</DataTemplate>
</Window.Resources>
<ListView Name="MovieListView" ItemTemplate="{StaticResource ItemTemplate}" ItemsSource="{Binding Path = movies}" Margin="0,0,0,0" SelectionChanged="MovieListView_SelectionChanged" Grid.Row="1">
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid Columns="5" />
</ItemsPanelTemplate>
</ListView.ItemsPanel>
</ListView>
However the issue is, I need each button to have a unique id. I read elsewhere that this can't be done in XAML but I'm not sure how or where in my C# code to create these buttons.
I think the most flexible solution here would be to define a behavior:
public class UniqueNameBehavior : Behavior<FrameworkElement>
{
protected override void OnAttached()
{
base.OnAttached();
//assign unique name to the associated element, for example:
AssociatedObject.Name = Guid.NewGuid().ToString().Replace("-", null);
}
}
In XAML, attach this behavior to any element:
<Button>
<i:Interaction.Behaviors>
<local:UniqueNameBehavior/>
</i:Interaction.Behaviors>
</Button>
where xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" from System.Windows.Interactivity assembly.
I have ItemsControl Binding to an ObservableCollection, every thing is ok except when ObservableCollection is empty, the ItemsControl will show one empty row !!
<ItemsControl Visibility="Visible" ItemsSource="{Binding ocItemsinInvoice,Mode=TwoWay}"
x:Name="test" Margin="10,-32,0,207" Width="412" HorizontalAlignment="Left">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid Columns="1" VerticalAlignment="Top" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button x:Name="btnOpenInvoice" Style="{StaticResource OpenInvoicesButton}"
FontSize="12" Width="300" Height="60" Foreground="#ff252526">
<StackPanel Orientation="Vertical">
<TextBlock Text="{Binding Item.ItemName}"
HorizontalAlignment="Center" VerticalAlignment="Center" />
</StackPanel>
</Button>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
How can I remove it?
public ObservableCollection<object> bindedObservableCollection
{
get{
ObservableCollection<object> newlist = new ObservableCollection<object>(yourObservableCollection);
return newlist;
}
}
I had this issue when binding to a list that was part of a datagrid, I found casting it to a new list of same type removed the blank editors record that is part of the datagrid.
I'm currently trying to figure out how to show different types of objects in a GridView, look at this Pic for example:
the last element on the right side is different than the other elements, so if i bind an observablecollection to the GridView, how can i say that the last element is shown up in anohter layout.
currently I'm using this XAML-Code
<GridView x:Name="startView" ItemsSource="{Binding}" Grid.Column="1" Grid.Row="2" SelectionMode="None" Width="Auto">
<GridView.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock x:Name="DetailTitle" Height="74" Text="{Binding Title}" />
<Image x:Name="Image" Height="Auto" Width="Auto" Margin="0" Stretch="None" Source="{Binding LocalCoverUrl}" Visibility="Collapsed" />
</StackPanel>
</DataTemplate>
</GridView.ItemTemplate>
<GridView.ItemsPanel>
<ItemsPanelTemplate>
<WrapGrid Orientation="Horizontal" MaximumRowsOrColumns="2" />
</ItemsPanelTemplate>
</GridView.ItemsPanel>
</GridView>
and this Code in the Back:
ObservableCollection<Movie> recentlyStarted = await Api.RecentlyStarted(3);
startView.DataContext = recentlyStarted;
but I have currently no clue how to let the last element show up in a different style
The easy way would be to have the two types of object as different classes (e.g. MoviePicStyle + MoviePlainStyle. Then move your DataTemplate out of the GridView, so that each object is picked up by type,
e.g.
<Window.Resources>
<DataTemplate DataType="{x:Type ViewModel:MoviePicStyle}">
<StackPanel>
<TextBlock x:Name="DetailTitle" Height="74" Text="{Binding Title}" />
<Image x:Name="Image" Height="Auto" Width="Auto" Margin="0" Stretch="None" Source="{Binding LocalCoverUrl}" Visibility="Collapsed" />
</StackPanel>
<DataTemplate DataType="{x:Type ViewModel:MoviePlainStyle}">
...Different View...
</DataTemplate>
</Window.Resources>
<GridView...
Use template selector property of gridview and depending upon the type of object select the template. I did the same in my project. you need to write your own DataTemplateSelector.
I referred below link
http://babaandthepigman.wordpress.com/2012/02/08/datatemplateselector-winrt/