My model is like so:
public class CPFF
{
public CMC Cmc { get; set; }
}
public class CMC
{
public List<CMCRecord> recordList { get; set; }
}
public class CMCRecord
{
public string name { get; set; }
public List<param> recordHeader { get; set; }
public List<param> paramList { get; set; }
public List<CmcStruct> structList { get; set; }
public bool IsEmptyRecord { get; set; }
public CpffConsts.CpffProjectVersion cpffProjectVersion { get; set; }
}
Here is my Xaml:
<TreeView DataContext="{Binding Cpff1StProjectObject}" SelectedItemChanged="TreeView_OnSelectedItemChanged" HorizontalContentAlignment="Stretch" >
<TreeViewItem Header="CMC" >
<TreeViewItem Header="RecordList" ItemsSource="{Binding Cmc.recordList}" >
<HierarchicalDataTemplate DataType="{x:Type types:CMCRecord}" ItemsSource="{Binding paramList}">
<TextBlock Text="{Binding Path=name, StringFormat={}CMCRecord : {0}}" />
</HierarchicalDataTemplate>
</TreeViewItem>
</TreeViewItem>
</TreeView>
<HierarchicalDataTemplate DataType="{x:Type types:param}">
<StackPanel>
<TextBlock Text="{Binding Path=name, StringFormat={}Name : {0}}" />
<TextBlock Text="{Binding Path=type, StringFormat={}Type : {0}}" />
<TextBlock Text="{Binding Path=description, StringFormat={}Description : {0}}" />
<TextBlock Text="{Binding Path=defaultValue, StringFormat={}DefaultValue : {0}}" />
<TextBlock Text="{Binding Path=domain_name, StringFormat={}domain_name : {0}}" />
<TextBlock Text="{Binding Path=notes, StringFormat={}Notes : {0}}" />
<TextBlock Text="{Binding Path=offset, StringFormat={}Offset : {0}}" />
<TextBlock Text="{Binding Path=bytes, StringFormat={}Bytes : {0}}" />
<TextBlock Text="{Binding Path=size, StringFormat={}Size : {0}}" />
<TextBlock Text="{Binding Path=min, StringFormat={}Min : {0}}" />
<TextBlock Text="{Binding Path=max, StringFormat={}Max : {0}}" />
</StackPanel>
</<HierarchicalDataTemplate DataType="{x:Type types:param}">
<StackPanel>
<TextBlock Text="{Binding Path=name, StringFormat={}Name : {0}}" />
<TextBlock Text="{Binding Path=type, StringFormat={}Type : {0}}" />
<TextBlock Text="{Binding Path=description, StringFormat={}Description : {0}}" />
<TextBlock Text="{Binding Path=defaultValue, StringFormat={}DefaultValue : {0}}" />
<TextBlock Text="{Binding Path=domain_name, StringFormat={}domain_name : {0}}" />
<TextBlock Text="{Binding Path=notes, StringFormat={}Notes : {0}}" />
<TextBlock Text="{Binding Path=offset, StringFormat={}Offset : {0}}" />
<TextBlock Text="{Binding Path=bytes, StringFormat={}Bytes : {0}}" />
<TextBlock Text="{Binding Path=size, StringFormat={}Size : {0}}" />
<TextBlock Text="{Binding Path=min, StringFormat={}Min : {0}}" />
<TextBlock Text="{Binding Path=max, StringFormat={}Max : {0}}" />
</StackPanel>
</HierarchicalDataTemplate>>
This is how my tree look like:
Since CMCRecord Contains more than one list I would like to reflect it into the tool.
However since ItemSource in the HierarchicalDataTemplate is bound to paramlist,
How can I show more than one list inside my TreeView?
You will need to create a union of the various lists as a list of type object (i.e. List<object>) and set that as the Children target in your HierarchicalDataTemplate and use WPF type inference to determine the HierarchicalDataTemplate to be used, much like you have done for type param
Related
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>
I have a UserControl in ViewModel which is a Property in ViewModel. I will obtain this UserControl from some dll's.
private GraphicControl _graphicCtrl;
public GraphicControl GraphicCtrl
{
get { return _graphicCtrl; }
set
{
_graphicCtrl = value;
NotifyPropertyChanged();
}
}
In the above property, GraphicCtrl is nothing but a UserControl. I want to display this in my View (xaml). So how should I achieve this.?
Here is a very simple example how to separate this
public class MainViewModel : ReactiveObject
{
public MainViewModel()
{
Stuff = new ObservableCollection<object>
{
new Person { FirstName = "Jon", LastName="Doe", },
new Car { Brand = "Ford", Model = "Model T" },
};
}
public IEnumerable Stuff { get; }
[Reactive] public object SelectedStuff { get; set; }
}
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
public class Car
{
public string Brand { get; set; }
public string Model { get; set; }
}
As you can see, no dependency to any controls or other UI related stuff.
Now the view where I decide how to present the data from the ViewModel
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="200" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<ListBox
ItemsSource="{Binding Stuff}"
SelectedItem="{Binding SelectedStuff}">
<ListBox.Resources>
<DataTemplate DataType="{x:Type local:Car}">
<TextBlock>
<Run Text="{Binding Brand}" /><Run Text=" - " /><Run Text="{Binding Model}" />
</TextBlock>
</DataTemplate>
<DataTemplate DataType="{x:Type local:Person}">
<TextBlock>
<Run Text="{Binding FirstName}" /> <Run Text="{Binding LastName}" />
</TextBlock>
</DataTemplate>
</ListBox.Resources>
<ListBox.ItemTemplate>
<DataTemplate>
<ContentPresenter Content="{Binding}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<ContentControl
Grid.Column="1"
Content="{Binding SelectedStuff}">
<ContentControl.Resources>
<DataTemplate DataType="{x:Type local:Car}">
<local:CarControl/>
</DataTemplate>
<DataTemplate DataType="{x:Type local:Person}">
<local:PersonControl/>
</DataTemplate>
</ContentControl.Resources>
</ContentControl>
</Grid>
the CarControl
<StackPanel>
<Label Content="Car" />
<Label Content="Brand" />
<TextBlock Text="{Binding Brand}" />
<Label Content="Model" />
<TextBlock Text="{Binding Model}" />
</StackPanel>
the PersonControl
<StackPanel>
<Label Content="Person" />
<Label Content="FirstName" />
<TextBlock Text="{Binding FirstName}" />
<Label Content="LastName" />
<TextBlock Text="{Binding LastName}" />
</StackPanel>
and finally a screenshot
I want to display this in my View (xaml). So how should I achieve this.?
Short answer: Use a ContentControl and bind its Content property to the UserControl:
<ContentControl Content="{Binding GraphicCtrl}" />
As others have already mentioned, exposing a UserControl from a view model is not MVVM though.
You should rather expose a POCO data object called Graphic or something and then use a DataTemplate to map this type to a UserControl in the view:
<ContentControl Content="{Binding Graphic}">
<ContentControl.ContentTemplate>
<DataTemplate>
<local:GraphicControl />
</DataTemplate>
</ContentControl.ContentTemplate>
</ContentControl>
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!
I've this template of ListBoxItem that contains an Image and TextBlock. How to add an Item to this ListBox from code?
<ListBox Name="listBox">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" >
<Image Source="{Binding}" Width="16" />
<TextBlock Text="{Binding}" Margin="5,0,0,0" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
I am assuming you will want to have a class which has imagesource and text properties in the lines of
public class TestClass()
{
public string ImageSrc {get; set;}
public string DisplayText {get; set;}
}
Add the objects to your collection
listBox.Items.Add(new TestClass() { ImageSrc = "blahblah", DisplayTest = "Test Display Text" });
and so on
Then you can use xaml in the lines of
<ListBox Name="listBox">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" >
<Image Source="{Binding ImageSrc}" Width="16" />
<TextBlock Text="{Binding DisplayText}" Margin="5,0,0,0" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
I have tried for several hours and searching on the net for examples on how to pull multiple elements with the same name however different attributes and binding those to my XAML in my app for wp7,
the easiest way for me to explain is to simply show you,
heres what I have so far
public class Match
{
public string HomeTeam { get; set; }
public string AwayTeam { get; set; }
public string HomeScore { get; set; }
public string AwayScore { get; set; }
public string GoalsPlayer { get; set; }
public string goal { get; set; }
public string GoalsTime { get; set; }
public string DismissalsPlayer { get; set; }
public string DismissalsTime { get; set; }
public string BookingPlayer { get; set; }
public string BookingTime { get; set; }
public string GameTime { get; set; }
}
void wc_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
XElement element = XElement.Parse(e.Result);
try
{
listBox2.ItemsSource = from item in element.Descendants("competition")
from match in item.Elements("match").Where(arg => arg.Attribute("awayTeam").Value == team | arg.Attribute("homeTeam").Value == team)
select new Match
{
HomeTeam = (string)match.Attribute("homeTeam"),
AwayTeam = (string)match.Attribute("awayTeam"),
HomeScore = (string)match.Attribute("homeTeamScore"),
AwayScore = (string)match.Attribute("awayTeamScore"),
GoalsPlayer = (string)match.Attribute("playerName"),
GoalsTime = (string)match.Attribute("time"),
};
}
catch (Exception ex)
{
Debug.WriteLine(ex.StackTrace);
}
here is my XAML
<ListBox Name="listBox2" Grid.Row="0">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Name="teams" Orientation="Vertical">
<StackPanel Orientation="Horizontal">
<TextBlock Margin="0,10,0,0" Foreground="White" HorizontalAlignment="Left" Text="{Binding HomeTeam}"/>
<TextBlock Margin="10,10,30,0" Foreground="White" Text="{Binding HomeScore}" TextWrapping="Wrap" FontSize="20" />
<TextBlock Margin="0,10,0,0" Foreground="White" HorizontalAlignment="Left" Text="{Binding AwayTeam}"/>
<TextBlock Margin="10,10,30,0" Foreground="White" Text="{Binding AwayScore}" TextWrapping="Wrap" FontSize="20" />
</StackPanel>
<StackPanel Name="scores" Orientation="Horizontal">
<TextBlock Margin="0,10,0,0" Foreground="White" Text="{Binding GoalsPlayer}" TextWrapping="Wrap" FontSize="20" />
<TextBlock Margin="10,10,30,0" Foreground="White" Text="{Binding GoalsTime}" TextWrapping="Wrap" FontSize="20" />
</StackPanel>
<StackPanel Name="dismissals">
<TextBlock Foreground="White" Text="{Binding DismissalsPlayer}" TextWrapping="Wrap" FontSize="20"/>
<TextBlock Foreground="White" Text="{Binding DismissalsTime}" TextWrapping="Wrap" FontSize="20"/>
</StackPanel>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
here is my XML
<match homeTeam="Arsenal" awayTeam="Liverpool" homeTeamScore="0" awayTeamScore="2">
<goal time="77:13" playerName="Aaron Ramsey" />
<goal time="89:57" playerName="Luis Suarez"/>
<dismissal time="69:59" playerName="Emmanuel Frimpong"/>
</match>
I understand that I will only get one entry on my Page for Goals, which would be the first goal element in my XML
how can I go about that and implement every
<goal ...>
<goal ...>
into my Datatemplate that currently only shows the first entry, another potential problem is I cannot guarantee how many goals there will be so I am a really unsure on how to go about it entirely
thanks
John
Should playerName even resolve on your match? Because that's where you are resolving it in your XML query.
Regardless, what you are looking for here is a sub-object that can be held in a list property of the Match object:
listBox2.ItemsSource = from item in element.Descendants("competition")
from match in item.Elements("match")
.Where(arg => arg.Attribute("awayTeam").Value == team ||
arg.Attribute("homeTeam").Value == team)
select new Match
{
HomeTeam = (string)match.Attribute("homeTeam"),
AwayTeam = (string)match.Attribute("awayTeam"),
HomeScore = (string)match.Attribute("homeTeamScore"),
AwayScore = (string)match.Attribute("awayTeamScore"),
Goals = match.Elements("goals").Select(ev => new MatchEvent
{
Player = (string)ev.Attribute("playerName"),
Time = (string)ev.Attribute("time")
}).ToList(),
Dismissals = match.Elements("dismissals").Select(ev => new MatchEvent
{
Player = (string)ev.Attribute("playerName"),
Time = (string)ev.Attribute("time")
}).ToList(),
};
And the updated XAML:
<ListBox Name="listBox2" Grid.Row="0">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Name="teams" Orientation="Vertical">
<StackPanel Orientation="Horizontal">
<TextBlock Margin="0,10,0,0" Foreground="White" HorizontalAlignment="Left" Text="{Binding HomeTeam}"/>
<TextBlock Margin="10,10,30,0" Foreground="White" Text="{Binding HomeScore}" TextWrapping="Wrap" FontSize="20" />
<TextBlock Margin="0,10,0,0" Foreground="White" HorizontalAlignment="Left" Text="{Binding AwayTeam}"/>
<TextBlock Margin="10,10,30,0" Foreground="White" Text="{Binding AwayScore}" TextWrapping="Wrap" FontSize="20" />
</StackPanel>
<ItemsControl ItemsSource="{Binding Goals}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Name="scores" Orientation="Horizontal">
<TextBlock Margin="0,10,0,0" Foreground="White" Text="{Binding Player}" TextWrapping="Wrap" FontSize="20" />
<TextBlock Margin="10,10,30,0" Foreground="White" Text="{Binding Time}" TextWrapping="Wrap" FontSize="20" />
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<ItemsControl ItemsSource="{Binding Dismissals}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Name="scores" Orientation="Horizontal">
<TextBlock Margin="0,10,0,0" Foreground="White" Text="{Binding Player}" TextWrapping="Wrap" FontSize="20" />
<TextBlock Margin="10,10,30,0" Foreground="White" Text="{Binding Time}" TextWrapping="Wrap" FontSize="20" />
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>