Binding Command in DataTemplate - c#

I made UWP app with MVVM pattern(i think so :) )
My app have data template for listbox.
ListBox in View.xaml:
<ListBox x:Name="lbMySongs" ItemsSource="{Binding Path=MySongs}" ItemTemplate="{StaticResource lbSongsTemplate}" Grid.Row="1">
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
</Style>
</ListBox.ItemContainerStyle>
</ListBox/>
DateTemplate resource:
<DataTemplate x:Key="lbSongsTemplate">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto"/>
<ColumnDefinition Width="auto"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="auto"/>
<ColumnDefinition Width="auto"/>
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding Path=Artist}" Grid.Column="0"/>
<TextBlock Text=" - " Grid.Column="1"/>
<TextBlock Text="{Binding Path=Title}" Grid.Column="2"/>
//Here i bind command, but it's not binding cos ItemsSource have no command. ViewModel have this command.
<Button Command="{Binding Path=DownloadCommand}" Content="{Binding Path=Query}"/>
<TextBlock Text="{Binding Duration}" Grid.Column="5" HorizontalAlignment="Right"/>
</Grid>
</DataTemplate>
Need to set DataContext for this button.
My command in ViewModel. Example:
class ViewModel
{
...
public RelayCommand DownloadCommand { get; set; }
public ObservableCollection<SomeClass> MySongs { get; set; }
...
}
My problem: DataTemplate have ItemsSource = ViewModel.MySongs. But "DownloadCommand" is in ViewModel.
What i type in DataTemplate for my button set binding to DownloadCommand?

Try to use:
<Button Command="{Binding Path=DataContext.DownloadCommand, ElementName=lbMySongs}"
CommandParameter="{Binding}"
Content="{Binding Path=Query}"/>
And change
public RelayCommand DownloadCommand { get; set; }
to
public RelayCommand<SomeClass> DownloadCommand { get; set; }
...
DownloadCommand = new RelayCommand<SomeClass>(DownloadExecute);
...
private voir DownloadExecute(SomeClass item)
{
...
}

Use a RelativeSource binding to say you want to bind to ListBox.DataContext.DownloadCommand
<Button Command="{Binding Path=DataContext.DownloadCommand,
RelativeSource={RelativeSource AncestorType={x:Type ListBox}}}"
Content="{Binding Path=Query}"/>
Its often common practice like this to also bind the CommandParameter to the item to know what item the command was executed on :
<Button Command="{Binding Path=DataContext.DownloadCommand,
RelativeSource={RelativeSource AncestorType={x:Type ListBox}}}"
CommandParameter="{Binding }"
Content="{Binding Path=Query}" />
You could also use an ElementName binding, but then you have to give your ListBox a Name to specify in your DataTemplate, and I don't personally like to hardcode ElementName in my DataTemplates. Makes it annoying to find and fix if you change something's name, or want to use the DataTemplate in another ListBox.

Related

UserControls aren't displayed properly in ListBox when added from Code-behind (C#, WPF)

I got a simple UserControl that is basically just a Grid with 6 Columns and a bunch of TextBlocks.
XAML:
<UserControl x:Class="MyApplication.TimeAccountItem"
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:MyApplication"
mc:Ignorable="d">
<UserControl.Resources>
<local:TimeSpanConverter x:Key="TimeSpanConverter"/>
<Style TargetType="TextBlock">
<Setter Property="FontSize" Value="14"/>
<Setter Property="Margin" Value="10,5"/>
<Setter Property="TextAlignment" Value="Center"/>
</Style>
</UserControl.Resources>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="48"/>
<ColumnDefinition Width="2*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" x:Name="tb_Id" Text="{Binding User, FallbackValue=0}"/>
<TextBlock Grid.Column="1" x:Name="tb_Employee" Text="{Binding Alias, FallbackValue=Employee}"/>
<TextBlock Grid.Column="2" x:Name="tb_Updated" Text="{Binding Updated, StringFormat=dd.MM.yyy, FallbackValue=00.00.0000}"/>
<TextBlock Grid.Column="3" x:Name="tb_Total" Text="{Binding Total, Converter={StaticResource TimeSpanConverter}, FallbackValue=00:00 h}"/>
<TextBlock Grid.Column="4" x:Name="tb_Claimed" Text="{Binding Claimed, Converter={StaticResource TimeSpanConverter}, FallbackValue=00:00 h}"/>
<TextBlock Grid.Column="5" x:Name="tb_Remaining" Text="{Binding Remaining, Converter={StaticResource TimeSpanConverter}, FallbackValue=00:00 h}"/>
</Grid>
</UserControl>
CS:
public partial class TimeAccountItem : UserControl
{
public TimeAccount content { get; set; }
public OvertimeListBoxItem(TimeAccount timeAccount)
{
content = timeAccount;
this.DataContext = content;
}
public OvertimeListBoxItem()
{
InitializeComponent();
}
}
On my MainWindow I got a ListBox where I want to "output" those UserControls.
When I do this in XAML everything works fine.
<ListBox Height="400" Margin="10,0" HorizontalContentAlignment="Stretch" BorderThickness="0" Name="listbox">
<local:TimeAccountItem/>
<local:TimeAccountItem/>
<local:TimeAccountItem/>
<local:TimeAccountItem/>
<local:TimeAccountItem/>
</ListBox>
However not from Code-behind
foreach (TimeAccount ta in timeAccountList)
{
listbox.Items.Add(new TimeAccountItem(ta));
}
I hovered one of the Items to show what happens. Already gave my UserControl a fixed Height instead of Auto but this didn't help either.
What am I doing wrong here?
Thanks in advance!
The UserControl constructor with TimeAccount argument is missing an InitializeComponent call:
public TimeAccountItem(TimeAccount timeAccount)
{
DataContext = timeAccount;
InitializeComponent();
}
You should however not be doing this at all.
Instead, declare an appropriate ItemTemplate:
<ListBox ...>
<ListBox.ItemTemplate>
<DataTemplate>
<local:TimeAccountItem/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Then remove the explicit DataContext assignment from the UserControl
public partial class TimeAccountItem : UserControl
{
public TimeAccountItem()
{
InitializeComponent();
}
}
and assign a collection of data items instead of UI elements to the ListBox's ItemsSource property:
listbox.ItemSource = timeAccountList;

I can't bind with the IsExpanded property on my treeview

I'm trying to bind with an IsExpanded property, but without success so far. I need to know when one of the groups is expanded.
<TreeView Grid.Row="1">
<!-- Encontrados -->
<TreeViewItem
FontWeight="Bold"
IsExpanded="True"
ItemsSource="{Binding Banco.Grupos}">
<TreeViewItem.Header>
<StackPanel Orientation="Horizontal">
<materialDesign:PackIcon
Width="20"
Foreground="Green"
Kind="Done" />
<TextBlock Text="ENCONTRADOS: " />
<TextBlock Text="{Binding SaldoEncontrados, StringFormat='{}{0:C}', ConverterCulture='PT-BR'}" />
</StackPanel>
</TreeViewItem.Header>
<TreeViewItem.ItemTemplate>
<HierarchicalDataTemplate DataType="{x:Type model:Grupo}" ItemsSource="{Binding Transações}">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Nome, StringFormat='{}{0}: '}" />
<TextBlock Text="{Binding ValorTotal, StringFormat='{}{0:C}', ConverterCulture='PT-BR'}" />
</StackPanel>
<HierarchicalDataTemplate.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto" />
<ColumnDefinition Width="auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="auto" />
</Grid.ColumnDefinitions>
<CheckBox
Grid.Column="0"
FontWeight="Normal"
IsChecked="{Binding isEnabled}" />
<TextBlock
Grid.Column="1"
FontWeight="Normal"
Text="{Binding Transação.DataDaTransação, StringFormat='dd/MM/yyyy'}" />
<TextBlock
Grid.Column="2"
Margin="10,0,10,0"
FontWeight="Normal"
Text="{Binding Transação.Historico}" />
<TextBlock
Grid.Column="3"
HorizontalAlignment="Right"
FontWeight="Normal"
Text="{Binding Transação.Valor, StringFormat='{}{0:C}', ConverterCulture='PT-BR'}" />
</Grid>
</DataTemplate>
</HierarchicalDataTemplate.ItemTemplate>
</HierarchicalDataTemplate>
</TreeViewItem.ItemTemplate>
</TreeViewItem>
<!-- Não Encontrados -->
<TreeViewItem
FontWeight="DemiBold"
IsExpanded="False"
ItemsSource="{Binding TransaçõesNãoEncontradas}">
<TreeViewItem.Header>
<StackPanel HorizontalAlignment="Left" Orientation="Horizontal">
<materialDesign:PackIcon
Width="20"
Foreground="Red"
Kind="Error" />
<TextBlock Text="NÃO ENCONTRADOS: " />
<TextBlock Text="{Binding SaldoNaoEncontrados, StringFormat='{}{0:C}', ConverterCulture='PT-BR'}" />
</StackPanel>
</TreeViewItem.Header>
<TreeViewItem.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto" />
<ColumnDefinition x:Name="Coluna1" Width="*" />
<ColumnDefinition Width="auto" />
</Grid.ColumnDefinitions>
<TextBlock
Grid.Column="0"
FontWeight="Normal"
Text="{Binding DataDaTransação, StringFormat='dd/MM/yyyy'}" />
<TextBlock
Grid.Column="1"
Margin="10,0,10,0"
FontWeight="Normal"
Text="{Binding Historico}" />
<TextBlock
Grid.Column="2"
HorizontalAlignment="Right"
FontWeight="Normal"
Text="{Binding Valor, StringFormat='{}{0:C}', ConverterCulture='PT-BR'}" />
</Grid>
</DataTemplate>
</TreeViewItem.ItemTemplate>
</TreeViewItem>
</TreeView>
My group class:
public class Grupo
{
public int Id { get; set; }
public int BancoId { get; set; }
public string Nome { get; set; }
public List<Transações> Transações { get; set; }
public decimal ValorTotal { get; set; }
public bool isExpanded { get; set; } = false;
public bool isZeroEnabled { get; set; }valores
}
public record Transações(int pk, int fk, bool isEnabled, OfxTransação Transação)
{
public bool isEnabled { get; set; } = isEnabled;
}
XAML:
Could someone help me bind the treeview's IsExpanded property so that I can know when a "Group" is expanded.
I created an example of my code: https://github.com/Foiolag/TreeviewExample
You can bind the IsExpanded property via ItemContainerStyle. Make sure to remove the explicite IsExpanded="True"
<!-- Encontrados -->
<TreeViewItem FontWeight="Bold"
ItemsSource="{Binding Banco.Grupos}">
<TreeViewItem.ItemContainerStyle>
<Style TargetType="TreeViewItem">
<Setter Property="IsExpanded" Value="{Binding IsExpanded, Mode=TwoWay}"/>
</Style>
</TreeViewItem.ItemContainerStyle>
Hint 1: This style will be inherited over all children, the application will also try to bind to the non existing IsExpanded property on your Transações object. This won't throw any exceptions, just binding errors. For the sake of consistency, I would rather implement the IsExpanded property on all children.
Hint 2: Your model classes are not bindable (do not notify property changes). If you change the properties after the view initialization, the view won't react to your changes. You have to implement INotifyPropertyChanged or use a base class like BindableBase. Read this. If the properties are intended for read-only use, better to make them read-only (remove setters).
Hint 3: Please avoid using special characters for your variables and class names 😉
The DataContext of the item container (in this case the TreeViewItem) is always the data item itself.
With this in mind you can setup the binding using a Style:
<Style TargetType="TreeViewItem">
<Setter Property="IsExpanded"
Value="{Binding IsExpanded, Mode=TwoWay}" />
</Style>

Validating ItemsControl in wpf didn't work

I have an ItemsControl to display translations text fields.
I want to setup validating, so if all translations are empty, there was an error, and fields was marked as "error".
Is there any possibilty to do this?
My xaml:
<ItemsControl x:Name="LanguageItemsControl" ItemsSource="{Binding Path=Translations, Mode=TwoWay}"
LostFocus="OnLostFocus" >
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid Margin="5,2,5,2">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="47*"/>
<ColumnDefinition Width="53*"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" x:Name="ItemLabel" VerticalAlignment="Center"
Text="{Binding Path=Key, StringFormat={x:Static res:Resources.lblCaption}}" />
<TextBox Grid.Column="1" x:Name="ItemText" VerticalAlignment="Center"
HorizontalAlignment="Stretch" Margin="2,0,22,0"
Text="{Binding Path=Value, Mode=TwoWay,
UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=true, NotifyOnValidationError=true}"
LostFocus="OnLostFocus"
AcceptsReturn="True"
MaxLines="2"
ScrollViewer.VerticalScrollBarVisibility="Auto"
MaxLength="150">
</TextBox>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
My model's class implements from IDataErrorInfo and INotifyPropertyChanged
Translations is an ObservableCollection of custom type "LanguageValue" with public properties Key and Value.
I had in my model string this[string columnName], which works perfect with simple text boxes (outside ItemsControl), but how can make this works with my items? I've thight something like:
public string this[string columnName]
{
get
{
string result = null;
...
if (columnName == "Translations" || columnName == "ItemText")
{
if (Translations.All(t => string.IsNullOrEmpty(t.Value)))
result = Properties.Resources.errMsgEnterName;
}
...
But of course this didn't work.
Any suggestions?
Sure, I'm giving you a full implementation but with just the "Value" property. Do the same with all other properties that you want to validate:
1.Translation Model with IDataErrorInfo interface implementation:
public class Translation : BindableBase, IDataErrorInfo
{
public string Value { get; set; }
public string this[string propertyName]
{
get
{
return GetErrorForPropery(propertyName);
}
}
public string Error { get; }
private string GetErrorForPropery(string propertyName)
{
switch (propertyName)
{
case "Value":
if (string.IsNullOrEmpty(Value))
{
return "Please enter value";
}
return string.Empty;
default:
return string.Empty;
}
}
}
2.Initialize Translations in your ViewModel:
public ObservableCollection<Translation> Translations { get; set; }
public MainViewModel()
{
Translations = new ObservableCollection<Translation>
{
new Translation {Value = "A"},
new Translation (),
new Translation {Value = "C"}
};
}
3.Xaml with ValidatesOnDataErrors on the Value TextBox:
<ItemsControl x:Name="LanguageItemsControl" ItemsSource="{Binding Path=Translations, Mode=TwoWay}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid Margin="5,2,5,2">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="47*"/>
<ColumnDefinition Width="53*"/>
</Grid.ColumnDefinitions>
<TextBox Grid.Column="0" x:Name="ItemLabel" VerticalAlignment="Center" Text="{Binding Path=Value, ValidatesOnDataErrors=True, UpdateSourceTrigger=PropertyChanged}" />
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
4.That will show a red box around the empty TextBox, if you want to display the error messeage when hovering overthe TextBox you need a tool tip:
<Window x:Class="WpfApplication1.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:customControlLib="clr-namespace:CustomControlLib;assembly=CustomControlLib"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
mc:Ignorable="d"
Title="MainWindow"
DataContext="{StaticResource MainViewModel}">
<Window.Resources>
<Style x:Key="TextBoxStyle" TargetType="{x:Type TextBox}">
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="true">
<Setter Property="ToolTip"
Value="{Binding RelativeSource={RelativeSource Self},
Path=(Validation.Errors)[0].ErrorContent}"/>
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>
<Grid>
<ItemsControl x:Name="LanguageItemsControl" ItemsSource="{Binding Path=Translations, Mode=TwoWay}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid Margin="5,2,5,2">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="47*"/>
<ColumnDefinition Width="53*"/>
</Grid.ColumnDefinitions>
<TextBox Grid.Column="0" x:Name="ItemLabel" Style="{StaticResource TextBoxStyle}" VerticalAlignment="Center" Text="{Binding Path=Value, ValidatesOnDataErrors=True, UpdateSourceTrigger=PropertyChanged}" />
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>

How to use a Binding of the ViewModel instead of the DataType of a ListView?

Let me begin with apologizing for the perhaps somewhat vague title, I'm having a hard time explaining my problem! Perhaps this is why I'm hardly getting any Google results, with this post being the closest to my problem (I think): How to bind to a property of the ViewModel from within a GridView
Anyways, I have a list of news articles that are being dynamically generated. The user has the option to press a "Star"-button in order to add an article to his/her favorites list. This "Star"-button should thus only be visible when the user is logged in.
I'm trying to achieve this by setting the Visibility of the Button to a property called IsLoggedIn inside my ViewModel. However, because this is happening inside my ListView it's trying to find the property IsLoggedIn inside of Article instead of the ViewModel.
So I guess my questions boils down to: How can I bind to a ViewModel property inside of a Databound ListView?
<ListView ItemsSource="{x:Bind VM.Articles, Mode=OneWay}" ItemClick="DebuggableListView_ItemClick" IsItemClickEnabled="True" SelectionMode="None" Grid.Row="1" VerticalAlignment="Top">
<ListView.ItemTemplate>
<DataTemplate x:DataType="models:Article">
<Grid Margin="0,10,10,10">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*"/>
<ColumnDefinition Width="4*"/>
</Grid.ColumnDefinitions>
<Image Source="{Binding Image}" Margin="0,0,10,0" Grid.Column="0" VerticalAlignment="Top" ImageFailed="Image_ImageFailed"/>
<Button Visibility="{x:Bind VM.IsLoggedIn, Converter={StaticResource BooleanToVisibilityConverter}, Mode=OneWay}" FontFamily="Segoe MDL2 Assets" Content="" FontSize="30" Background="Transparent" Grid.Column="1" HorizontalAlignment="Right" VerticalAlignment="Bottom"/>
<StackPanel Grid.Column="1">
<TextBlock TextWrapping="Wrap" FontWeight="Bold" Text="{Binding Title}"/>
<TextBlock TextWrapping="Wrap" Text="{Binding Summary}"/>
</StackPanel>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Requested Article class:
public sealed class Article
{
public int Id { get; set; }
public int Feed { get; set; }
public string Title { get; set; }
public string Summary { get; set; }
public DateTime PublishDate { get; set; }
public string Image { get; set; }
public string Url { get; set; }
public string[] Related { get; set; }
public Category[] Categories { get; set; }
public bool IsLiked { get; set; }
}
Okay, so currently I got it working by having a property which gets the singleton of my VM, however I'm sure there has to be a cleaner way to get something simple like this working. I've added a sample rar (OneDrive link: https://1drv.ms/u/s!Ar4fOTiwmGYnyWbwRY6rM0eFsL9x) which has a list, a ViewModel, some dummy data and a Visibility property inside the VM. If you can get it working without my dirty method please feel free to commit as an answer.
This type problem can best be solved using relative binding. Rather than binding directly to the current DataContext, i.e. this case the individual item in the ListView's ItemsSource, you can bind to a property of any ancestor element.
Given a simple ViewModel class
public class ViewModel: ViewModelBase
{
private bool _isLoggedIn;
public bool IsLoggedIn
{
get { return _isLoggedIn; }
set
{
_isLoggedIn = value;
RaisePropertyChanged(() => IsLoggedIn);
}
}
public IEnumerable<string> Items
{ get { return new[] {"One", "Two", "Theee", "Four", "Five"}; } }
}
the View can then be defined as
<Window x:Class="ParentBindingTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:ParentBindingTest"
Title="MainWindow"
Width="300" Height="400">
<Window.DataContext>
<local:ViewModel />
</Window.DataContext>
<Window.Resources>
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" />
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<CheckBox Margin="16,8" HorizontalAlignment="Left" Content="Logged In?" IsChecked="{Binding IsLoggedIn, Mode=TwoWay}" />
<ListView Grid.Row="1" Margin="16,8" ItemsSource="{Binding Items}">
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Button Visibility="{Binding Path=DataContext.IsLoggedIn, RelativeSource={RelativeSource AncestorType={x:Type ListView}}, Converter={StaticResource BooleanToVisibilityConverter}}">
<Image Source="Images\remove.png" />
</Button>
<TextBlock Text="{Binding}" />
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
</Window>
Note how in the item DataTemplate, the TextBlock's Text property is bound directly to the item.
However the Button's Visibility is bound not to a propery of it's own DataContext, but to that of the ListView itself, using relative binding.

Data Binding Help - WPF

I have those two classes:
class DownloadLink
{
public string Name { get; private set; }
public string Url { get; private set; }
//(...)
}
class DownloadGroup
{
public List<DownloadLink> Links { get; private set; }
//(...)
}
class Manager
{
public List<DownloadGroup> Groups { get; private set; }
}
Manager managerOBJ = new Manager();
I want to display this like that:
Everything will be in ListBox:
I wan to bind managerOBJ.Groups to that ListBox. - How to do it?
Than I want to create DataTamplate to display each group and all links in that group. - How to do it?
I want to do as much as possible from XAML
UPDATE:
This is what I got. It's not workig. List box is empty.
<ListBox DockPanel.Dock="Right" VerticalAlignment="Stretch" Width="500" HorizontalAlignment="Right" Background="#FFE1FFF5" HorizontalContentAlignment="Stretch" ScrollViewer.HorizontalScrollBarVisibility="Disabled" ScrollViewer.VerticalScrollBarVisibility="Visible" ItemsSource="{Binding Path=Groups}" Name="GroupsListBox">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Height="30" VerticalAlignment="Top" Width="500" >
<Grid Height="Auto" Width="500">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Label Content="XX MB w XX plikach" HorizontalAlignment="Stretch" Margin="0"/>
</Grid>
<ListBox HorizontalAlignment="Stretch" Height="43" Margin="0,5,0,0" Width="Auto" VerticalAlignment="Top" ItemsSource="{Binding Path=Links}">
<ListBox.ItemTemplate>
<DataTemplate>
<Label Content="{Binding Path=Name}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
and in code behid I have:
RapideoAccount = new Rapideo();
GroupsListBox.DataContext = RapideoAccount;
The whole manager is contained in a listbox, for each downloadgroup in the manager you add an itemscontrol that contains another items control with the links in it.
This can be done by using DataTemplates:
<ListBox Name="myGroups"
ItemsSource="{Binding Path=Groups}">
<!-- each List<DownloadGroup> in the manager: -->
<ListBox.ItemTemplate>
<DataTemplate>
<ItemsControl ItemsSource="{Binding Path=Links}">
<!-- each Link in the Downloadgroup -->
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding Path=Name}" />
<TextBlock Text="{Binding Path=Url}" />
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
In code you would put:
Manager managerOBJ = new Manager();
myGroups.DataContext = managerOBJ;
define managerOBJ as a property in your viewmodel
binding viewmodel to your view.
binding ListBox itemssource to managerOBJ.Groups.
define DataTemplate inside ListBox to display each DownloadGroup.

Categories