How to bind a ModelView item from a ObservableCollection in xml? - c#

I have a IntegerModelView and IntegerView and i want to reuse then in other view.
I am able to bind a ModelView but I want to bind a collection and i do not know how to select whole item from itermsource.
public class MultiValuedViewModel: PropertyChangedBase
{
private ObservableCollection<IntegerViewModel> _aded;
private IntegerViewModel _header;
....
}

Not checked, but something like this should work
<ItemsControl ItemsSource="{Binding Aded}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Vertical"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<!-- some data template -->
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>

Related

WPF Draw UserControl based on the Class of the bound object

im working on a menu which can display items.
Therefor i have a UserControl 'MenuItem' which displays an entity of the type 'MenuItemEntity'.
Cause there are submenus which are displayed in a different way there is another UserControl 'MenuItemGroup' which are bound to an entity of type 'MenuItemGroupEntity' containing different MenuItemEntities.
Now i have the following Problem:
The 'menu' should be bound to an entity of the type 'MenuEntity'.
Inside this i want to have an ObservableCollection which contains MenuItemEntity's AND MenuItemGroupEntity which are displayed in an StackPanel using an ItemsControl.
But i dont know if there is any way to analyze the actual element in the bound collection to draw either an MenuItem or an MenuItemGroup. Something like a switch maybe?
Normaly i would bind the items of the ObservableCollection in the 'MenuEntity' like this:
<ItemsControl ItemsSource="{Binding MenuItemAndGroupCollection}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Vertical"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<!-- IS THERE ANY WAY TO SWITCH BASED ON THE CLASS TYPE? -->
<local:MenuItemGroup DataContext="{Binding}" />
<local:MenuItem DataContext="{Binding}" />
<!-- IS THERE ANY WAY TO SWITCH BASED ON THE CLASS TYPE? -->
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
I hope someone can help me out of this =(
Simply use "implicit" DataTemplates, like this:
<Window>
<Window.Resources>
<DataTemplate DataType="{x:Type local:MyClass1}">
<local:MyUserControl1/>
</DataTemplate>
<DataTemplate DataType="{x:Type local:MyClass2}">
<local:MyUserControl2/>
</DataTemplate>
<!-- and so on... -->
</Window.Resources>
<ItemsControl ItemsSource="{Binding MenuItemAndGroupCollection}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Vertical"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<!-- Do NOT specify an ItemTemplate here -->
</ItemsControl>
</Window>

Binding To ICollectionView is not working

So, I am making a List of UserControl which ViewModel is assigned via ItemsControl
<ItemsControl Grid.Column="0" Grid.Row="1" x:Name="itemsControlStack"
ItemsSource="{Binding ListOfViewModels, Mode=OneWay}" VerticalAlignment="Bottom">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel IsItemsHost="True"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<local:UserControlA/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
Above code works, but I want to show it reversed, without changing the data, so :
<ItemsControl Grid.Column="0" Grid.Row="1" x:Name="itemsControlStack"
ItemsSource="{Binding REVERSEDListOfViewModels, Mode=OneWay}" VerticalAlignment="Bottom">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel IsItemsHost="True"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<local:UserControlA/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
Somewhere in my ViewModel, which I have checked via breakpoint that the code is executed
public ICollectionView REVERSEDListOfViewModels { get; private set; }
REVERSEDListOfViewModels = CollectionViewSource.GetDefaultView(ListOfViewModels);
REVERSEDListOfViewModels.SortDescriptions.Add(new SortDescription("ID", ListSortDirection.Descending));
But it suddenly not working. it doesn't return error anywhere, but UserControlA now don't properly presented. (The user control are presented without its data - which stored on the REVERSEDListOfViewModels)
Any idea why?

Data Binding UserControls to WrapPanel

I'm trying to work out how to Data Bind a list of UserControls to a WrapPanel but I'm not having much luck searching around.
I'm pretty new to WPF (come over from WinForms), at the moment I am adding the UserControls as children at runtime. Are there any solutions to this as I know WrapPanels don't support Data Binding.
Try something like this:
<ListBox ScrollViewer.HorizontalScrollBarVisibility="Disabled" ItemsSource="{Binding YourSource}">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel IsItemsHost="True" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
...
</ListBox>
If you don't need the selection stuff, you can try something with ItemsControl.
<ItemsControl ItemsControlScrollViewer.HorizontalScrollBarVisibility="Disabled" ItemsSource="{Binding YourSource}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel IsItemsHost="True" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
...
</ItemsControl>

An ItemsControl containing UserControl elements

I'm kind of shooting in the dark on this one and have been looking around but couldn't find much of anything related. Pretty much I am trying to create an ItemsControl on a current Window that I've got, so when the user clicks an "Add Product" button on the window, it will add a UserControl to the screen in a horizontal matter.
For starters I am using an MVVM pattern and I have a PricingViewModel which is my ViewModel for the MAIN window. I have a second view model named ComparisonViewModel, which is the ViewModel for the View of the UserControl that I would like to show everytime the user hits the "Add Product" button on the PricingView. Jumping into my code, I've got a declared ObservableCollection and my AddComparison method. The Collection is instantiated in the constructor of the VM.
public ObservableCollection<ComparisonViewModel> Products { get { return _products; } }
public void AddComparison()
{
var products = IoC.Get<ComparisonViewModel>();
Products.Add(products);
}
Next, I've got and ItemsControl in the PricingView that binds to that collection in the PricingViewModel:
<ItemsControl ItemsSource="{Binding Path=Products}" >
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" VerticalAlignment="Stretch"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
I run it and after hitting add, it just shows the collection name. How can I actually get it to Pop up with a new Comparison User Control when the user hits Add Comparison? Thanks a ton for the help in advance!
You'll want to set the ItemTemplate so the ItemsControl knows how to render each item in the collection (by default, it is just displaying the result of calling .ToString()).
<ItemsControl ItemsSource="{Binding Path=Products}" >
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" VerticalAlignment="Stretch"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate DataType="{x:Type namespace:ComparisonViewModel}">
<!-- EXAMPLE -->
<Border BorderBrush="Black"
BorderThickness="2">
<DockPanel Orientation="Horizontal">
<TextBlock Text="{Binding ComparisonResult}"
DockPanel.Dock="Right" />
<TextBlock Text="{Binding Name}"
DockPanel.Dock="Left" />
</DockPanel>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
I have found that I needed to tell the ItemsControl two things... First is what type of "thing" the ItemsControl is:
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
And the second is how to display the Control:
<ItemsControl.ItemTemplate>
<DataTemplate>
<c:Widget Margin="5" />
</DataTemplate>
</ItemsControl.ItemTemplate>
The final code looks like:
<ItemsControl ItemsSource="{Binding Path=DynamicItems}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<c:Widget Margin="5" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
You also need to add a reference to your control namespace in the window declaration stuff:
xmlns:c="clr-namespace:IHateEverything.Controls"

How to achieve hierarchical data binding?

Learning WPF here and I'm trying to get my head around hierarchical data binding.
This is my situation:
public class A
{
public int Id { ... }
public IEnumerable<B> Children { ... }
}
public class B
{
public string SomeValue { ... }
}
I want to use a ItemsControl to display a collection of A and for each occurance of A I want an inner ItemsControl to display A.Children.
I thought this would do the trick but, apparently, I have much to learn yet...
<ItemsControl x:Name="icCollectionOfAs" ItemsSource="{Binding}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid Width="auto" Height="auto">
<TextBlock Text="{Binding Id}" />
<ItemsControl ItemsSource="{Binding Children}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding SomeValue}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
Then, in code-behind...
icCollectionOfAs.ItemsSource = createSomeAsWithChildBsInThem();
The result of all this is nothing gets shown. Why?
Thanks
You should not specify the ItemsSource both in XAML (ItemsSource="{Binding}") and code behind (icCollectionOfAs.ItemsSource = createSomeAsWithChildBsInThem();) the XAML might have been called later.
The rest seems fine to me except that the TextBlock for the ID will probably be hidden behind the ItemsControl for the children as you use a Grid without rows or columns rather than a StackPanel.

Categories

Resources