UWP TreeView crash - c#

I have a TreeView (I almost copied the same code from XAML Controls Gallary):
<TreeView
x:Name="LocalFolderTreeView"
ItemTemplateSelector="{StaticResource FolderTreeTemplateSelector}"
ItemsSource="{x:Bind Tree, Mode=OneWay}"
Visibility="Collapsed" />
And the XAML of ItemTemplateSelector:
<DataTemplate x:Key="FolderTemplate" x:DataType="data:FolderTree">
<TreeViewItem
DoubleTapped="FolderTreeItem_DoubleTapped"
IsDoubleTapEnabled="True"
IsExpanded="False"
ItemsSource="{x:Bind Files}">
<StackPanel Orientation="Horizontal">
<StackPanel.ContextFlyout>
<MenuFlyout Opening="OpenPlaylistFlyout" />
</StackPanel.ContextFlyout>
<SymbolIcon Symbol="Folder" />
<TextBlock Margin="0,0,10,0" />
<TextBlock Text="{x:Bind Path}" />
</StackPanel>
</TreeViewItem>
</DataTemplate>
<DataTemplate x:Key="FileTemplate" x:DataType="data:Music">
<TreeViewItem>
<StackPanel
DoubleTapped="FileItem_DoubleTapped"
IsDoubleTapEnabled="True"
Orientation="Horizontal">
<StackPanel.ContextFlyout>
<MenuFlyout Opening="OpenMusicFlyout" />
</StackPanel.ContextFlyout>
<Image Width="20" Source="Assets/colorful_no_bg.png" />
<TextBlock Margin="0,0,10,0" />
<TextBlock Text="{x:Bind Name}" />
</StackPanel>
</TreeViewItem>
</DataTemplate>
<templateselector:FolderTreeTemplateSelector
x:Key="FolderTreeTemplateSelector"
FileTemplate="{StaticResource FileTemplate}"
FolderTemplate="{StaticResource FolderTemplate}" />
C# of ItemTemplateSelector is
public class FolderTreeTemplateSelector : DataTemplateSelector
{
public DataTemplate FolderTemplate { get; set; }
public DataTemplate FileTemplate { get; set; }
protected override DataTemplate SelectTemplateCore(object item, DependencyObject container)
{
if (item is Models.FolderTree) return FolderTemplate;
if (item is Models.Music) return FileTemplate;
return null;
}
}
It is used here
My ViewModels are defined here.
When I add this to the TreeView, my app crashes. Tree is not null because I also defined GridView that allows me to see it.
ItemsSource="{x:Bind Tree, Mode=OneWay}"
What is wrong?

The default ItemsSource is collection type, but in above code the Tree data source is FolderTree, it will cause argument error, please modify it as collection base on your actual data structure.

Related

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>

use binds in viewmodels

I am doing a project and in one xaml page I have some Textblock with bind like this
<PivotItem Header="Lista">
<ListView x:Name="List1" ItemsSource="{x:Bind ProdutoViewModel.Produtos}">
<ListView.ItemTemplate>
<DataTemplate x:DataType="list:Produto">`
...
<StackPanel>
<TextBlock x:Name="nome" Text="{x:Bind Nome, Mode=OneWay}" />
<TextBlock Text="{x:Bind Preco, Mode=OneWay}" />
<TextBlock Text="{x:Bind Disponivel, Mode=OneWay}" />
<TextBlock Text="{x:Bind Fornecedor, Mode=OneWay}" />
<TextBlock Text="{x:Bind Categoria, Mode=OneWay}" />
<Image Source="Assets/mouse.png" />
<Image Source="Assets/teclado.png"/>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</PivotItem>
And then I have another pivot like this
<PivotItem>
<PivotItem Header="Carrinho">
<ListView x:Name="Cart" ItemsSource="{x:Bind EncomendaProdutoViewModel.EncomendaProdutos}">
<ListView.ItemTemplate>
<DataTemplate x:DataType="list:EncomendaProduto">
<StackPanel>
<Button x:Name="pay" Content="Pagar" Click="Payment_click"/>
<TextBlock Text="{x:Bind Quantidade, Mode=OneWay}" />
<TextBlock Text="{x:Bind Preco, Mode=TwoWay}" />
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</PivotItem>
How can I show the data from the first pivot into the second? I have a button on the first pivotitem for each product and when I press it, I want to add the data of that product to the second pivotitem.
Create an outer view-model, like this:
<Page.DataContext>
<vm:MasterViewModel x:Name="ViewModel" />
</Page.DataContext>
class MasterViewModel
{
public ProdutoViewModel ProdutoViewModel { get; set; }
public EncomendaProdutoViewModel EncomendaProdutoViewModel { get; set; }
}
Then bind to the Pivot like this:
<Pivot>
<PivotItem>
<ListView ItemsSource="{x:Bind ViewModel.ProdutoViewModel.Produtos}"
SelectedItem="{x:Bind ViewModel.SelectedItem, Mode=TwoWay}" />
</PivotItem>
<PivotItem>
<ListView ItemsSource="{x:Bind ViewModel.EncomendaProdutoViewModel.EncomendaProdutos}"
SelectedItem="{x:Bind ViewModel.EncomendaProdutoViewModelSelectedItem, Mode=TwoWay}" />
</PivotItem>
</Pivot>
Then, handle the selection in code-behind:
class MasterViewModel
{
public ProdutoViewModel ProdutoViewModel { get; set; }
public EncomendaProdutoViewModel EncomendaProdutoViewModel { get; set; }
Producto _ProdutoViewModel;
public Producto ProdutoViewModel
{
get { return _ProdutoViewModel; }
set {
_ProdutoViewModel = value;
EncomendaProdutoViewModel.EncomendaProdutos.Add(value);
}
}
}
I hope this makes sense.
Best of luck!

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.

TreeView databinding problems with Silverlight and Caliburn Micro

I have using Silverlight and Caliburn Micro and am having a problem getting child nodes to appear in the tree. The TreeView is contaimed in a grid and here is my XAML excerpt:
<Grid.Resources>
<sdk:HierarchicalDataTemplate x:Key="AccountTemplate">
<TextBlock Text="{Binding AccountNumber}" />
</sdk:HierarchicalDataTemplate>
<sdk:HierarchicalDataTemplate x:Key="CategoryTemplate"
ItemsSource="{Binding CategoryServices}"
ItemTemplate="{StaticResource AccountTemplate}">
<TextBlock Text="{Binding Path=CategoryName}" FontWeight="Bold" />
</sdk:HierarchicalDataTemplate>
</Grid.Resources>
<Controls:TreeView Grid.Row="1" Grid.Column="0"
ItemsSource="{Binding FromAddressServices}"
ItemTemplate="{StaticResource CategoryTemplate}" x:Name="FromTreeView" />
The classes that are bound are:
public class AccountAtAddress
{
public string AccountNumber { get; set; }
}
public class ServiceCategory
{
public string CategoryName { get; set; }
public ObservableCollection<AccountAtAddress> CategoryServices;
}
The problem that I have is that the first level items show but no children. Does anyone have ideas for how to make this work?
You need to make CategoryServices into a public property. You have it defined as a public field and the databinding mechanism doesn't work with fields.
Try the following instead:
<Grid.Resources>
<sdk:HierarchicalDataTemplate DataType="AccountAtAddress">
<TextBlock Text="{Binding AccountNumber}" />
</sdk:HierarchicalDataTemplate>
<sdk:HierarchicalDataTemplate DataType="ServiceCategory"
ItemsSource="{Binding CategoryServices}">
<TextBlock Text="{Binding Path=CategoryName}" FontWeight="Bold" />
</sdk:HierarchicalDataTemplate>
</Grid.Resources>

Can't cast treeviewitem as treeviewitem in wpf

I've got webservice asmx, and there are classes:
Country
public string Name {get;set;}
public string Code {get;set;}
public List<Area> Areas {get;set;}
Area
public string Name {get;set;}
public string Code {get;set;}
public List<Regions> Provinces {get;set;}
Provinces
public string Name {get;set;}
public string Code {get;set;}
I bind it to mz TreeView WPF:
Country[] items = new MyService().GetListOfCountries();
structureTree.ItemsSource = items;
Code of myTree:
<UserControl x:Class="ObjectsAndZonesSimpleTree"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
<Grid>
<StackPanel Name="stackPanel1">
<GroupBox Header="Choose" Height="354" Name="groupBox1" Width="Auto">
<TreeView Name="structureTree" SelectedItemChanged="structureTree_SelectedItemChanged" Grid.Row="0" Grid.Column="0" ItemsSource="{Binding}" Height="334" ScrollViewer.VerticalScrollBarVisibility="Visible" ScrollViewer.HorizontalScrollBarVisibility="Visible" Width="Auto" PreviewMouseRightButtonUp="structureTree_PreviewMouseRightButtonUp" FontFamily="Verdana" FontSize="12" BorderThickness="1" MinHeight="0" Padding="1" Cursor="Hand" Margin="-1">
<TreeView.Resources>
<HierarchicalDataTemplate DataType="{x:Type MyService:Country}"
ItemsSource="{Binding Path=ListOfRegions}">
<StackPanel Orientation="Horizontal">
<TextBlock TextAlignment="Justify" VerticalAlignment="Center" Text="{Binding Path=Name}"/>
</StackPanel>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate DataType="{x:Type MyService:Region}"
ItemsSource="{Binding Path=Provinces}">
<StackPanel Orientation="Horizontal">
<TextBlock TextAlignment="Justify" VerticalAlignment="Center" Text="{Binding Path=Name}"/>
</StackPanel>
</HierarchicalDataTemplate>
<DataTemplate DataType="{x:Type MyService:Province}"
ItemsSource="{Binding Path=ListOfCities}">
<StackPanel Orientation="Horizontal">
<TextBlock TextAlignment="Justify" VerticalAlignment="Center" Text="{Binding Path=Name}"/>
</StackPanel>
</DataTemplate>
</TreeView.Resources>
</TreeView>
</GroupBox>
</StackPanel>
</Grid>
</UserControl>
This gives me null:
private void structureTree_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
{
TreeViewItem treeViewItem = structureTree.SelectedItem as TreeViewItem;
}
SelectedItem will actually contain a Country, Area, or Region (or null). If you really want the TreeViewItem, you can do strutureTree.ItemContainerGenerator.ContainerFromItem(structureTree.SelectedItem).
Correct. You should expect a Country as your SelectedItem. WPF works entirely different than Windows Forms did. It's all about databinding!

Categories