I am using TreeView to display my data. I want to bind foreground of a tree view item. Here is my code below.
View:
<UserControl.Resources>
<HierarchicalDataTemplate x:Key="TreeViewItem" ItemsSource="{Binding Children}">
<StackPanel Orientation="Horizontal">
<CheckBox Margin="2" IsChecked="{Binding IsChecked, Mode=TwoWay}" Content="{Binding Title}"
Background="{Binding Path=ForegroundColor}" IsThreeState="True"/>
</StackPanel>
</HierarchicalDataTemplate>
</UserControl.Resources>
<Grid>
<TreeView Margin="5, 0, 5, 0" ItemsSource="{Binding GeoGraphixModules}" ItemTemplate="{StaticResource TreeViewItem}" IsEnabled="{Binding TreeViewEnabled}" />
</Grid>
And in my view model
public class SomeTreeViewItem
{
public Collection Children
{
get { return _children; }
}
public Brush ForegroundColor
{
get
{
if (SomeCheck)
return Brushes.Green;
else
return Brushes.Red;
}
}
}
Now when I debug this application 'ForegroundColor' is hit but the application still displays black as foreground for all the child items. What is the problem here?
After trying to create the same error i made the following viewmodel
public class ViewModel
{
private Collection<GeoGraphixModule> _geoGraphixModules;
public ViewModel()
{
_geoGraphixModules = new Collection<GeoGraphixModule>();
_geoGraphixModules.Add(new GeoGraphixModule(){Children = new Collection<Bla>(){new Bla{Children = new Collection<Bla>{new Bla(), new Bla(), new Bla()}}}});
_geoGraphixModules.Add(new GeoGraphixModule(){Children = new Collection<Bla>(){new Bla{Children = new Collection<Bla>{new Bla(), new Bla(), new Bla()}}}});
_geoGraphixModules.Add(new GeoGraphixModule(){Children = new Collection<Bla>(){new Bla{Children = new Collection<Bla>{new Bla(), new Bla(), new Bla()}}}});
_geoGraphixModules.Add(new GeoGraphixModule(){Children = new Collection<Bla>(){new Bla{Children = new Collection<Bla>{new Bla(), new Bla(), new Bla()}}}});
}
public Collection<GeoGraphixModule> GeoGraphixModules
{
get { return _geoGraphixModules; }
set { _geoGraphixModules = value; }
}
}
public class GeoGraphixModule
{
public Brush ForegroundColor
{
get
{
if (SomeCheck())
return Brushes.Green;
return Brushes.Red;
}
}
private bool SomeCheck()
{
Random random = new Random();
int randomNumber = random.Next(0, 100);
if ((randomNumber % 2) == 0)
return true;
return false;
}
private Collection<Bla> _children;
public Collection<Bla> Children { get; set; }
}
public class Bla
{
private bool? _isChecked;
private string _title;
private Collection<Bla> _children;
public bool? IsChecked
{
get { return _isChecked; }
set
{
_isChecked = value;
}
}
public Collection<Bla> Children
{
get { return _children; }
set { _children = value; }
}
public string Title
{
get { return _title; }
set
{
_title = value;
}
}
}
Its very ugly i know but it works for the top level take a loot at the below image
Related
I want to show user's Folder
(C:\Food\BBQ\Recipe\Recipefile.txt)
enter image description here
enter image description here
like that
but result is ...
enter image description here
I make a project MVVM patteron wpf
Using ViewModel.cs and View
with HierarchicalDataTemplate
this is my codes
window1.xaml
<Window.Resources>
<ObjectDataProvider x:Key="ObjectDataProviderKey">
<ObjectDataProvider.ObjectInstance>
<vm:FolderViewModel FullPath="C:\Food"/>
</ObjectDataProvider.ObjectInstance>
</ObjectDataProvider>
<HierarchicalDataTemplate
DataType="{x:Type vm:FolderViewModel}"
ItemsSource="{Binding Path=SubFolderCollection}">
<TextBlock Text="{Binding Path=Name}" />
</HierarchicalDataTemplate>
<TreeView Name="folderTreeView" Grid.ColumnSpan="2" Grid.Row="2">
<TreeViewItem
Header="Favorit"
ItemsSource="{Binding Source={StaticResource ObjectDataProviderKey}, Path=SubFolderCollection}" />
</TreeView>
and
viewModel
FolderViewModel.cs
namespace TEST.ViewModels.TreeView
{
public class FolderViewModel : INotifyPropertyChanging
{
namespace TEST.ViewModels.TreeView
{
public class FolderViewModel : INotifyPropertyChanging
{
#region Field
private DirectoryInfo directoryInfo;
private ObservableCollection<FolderViewModel> subFolderCollection;
private ObservableCollection<FileInfo> fileInfoCollection;
#endregion
#region - FullPath
public string FullPath
{
get
{
return directoryInfo.FullName;
}
set
{
if (Directory.Exists(value))
{
directoryInfo = new DirectoryInfo(value);
}
else
{
throw new ArgumentException("No exist.", "FullPath");
}
}
}
#endregion
#region - Name
private string _Name = string.Empty;
public event PropertyChangingEventHandler PropertyChanging;
public string Name
{
get
{
_Name = directoryInfo.Name;
return _Name;
}
set
{
_Name = value;
OnpropertyChanaged("Name");
}
}
private void OnpropertyChanaged(string v)
{
throw new NotImplementedException();
}
#endregion
#region - SubFolderCollection
public ObservableCollection<FolderViewModel> SubFolderCollection
{
get
{
if (subFolderCollection == null)
{
subFolderCollection = new ObservableCollection<FolderViewModel>();
DirectoryInfo[] directoryInfoArray = directoryInfo.GetDirectories();
//DirectoryInfo[] directoryInfoArray = (DirectoryInfo[])this.directoryInfo.GetFileSystemInfos();
for (int i = 0; i < directoryInfoArray.Length; i++)
{
FolderViewModel folder = new FolderViewModel();
FullPath = directoryInfoArray[i].FullName;
this.subFolderCollection.Add(folder);
}
}
return subFolderCollection;
}
}
#endregion
#region FileInfoCollection
public ObservableCollection<FileInfo> FileInfoCollection
{
get
{
if (this.fileInfoCollection == null)
{
this.fileInfoCollection = new ObservableCollection<FileInfo>();
FileInfo[] fileInfoArray = this.directoryInfo.GetFiles();
for (int i = 0; i < fileInfoArray.Length; i++)
{
this.fileInfoCollection.Add(fileInfoArray[i]);
}
}
return this.fileInfoCollection;
}
}
#endregion
#region - Folder()
public FolderViewModel()
{
FullPath = #"C:\Food\";
}
#endregion
}
}
what should i do ??
If I understood you correctly. To Achieive the way you wanted you can do something like this.
MainWindow.xaml
<TreeView ItemsSource="{Binding TreeModel}">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Child}">
<Grid>
<Label Content="{Binding Name}"/>
</Grid>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
And Then your ViewModel you can create a collection which goes through your folders and add folder and file name
MainViewModel.cs
public ObservableCollection<DirModel> TreeModel { get; set; }
public MainViewModel()
{
TreeModel = new ObservableCollection<DirModel>();
Load();
}
void Load()
{
var root = "C:\\TEST";
foreach (var dirInfo in new DirectoryInfo(root).GetDirectories())
{
var dir = new DirModel() { Name = dirInfo.Name };
foreach (var sb in dirInfo.GetDirectories())
{
var sDir = new ChildDirModel() { Name = sb.Name };
var sFile = new FileModel() { Name = sb.GetFiles().First().Name };
sDir.Child.Add(sFile);
dir.Child.Add(sDir);
}
TreeModel.Add(dir);
}
}
Finally create a Model class which represent your structure
public class DirModel
{
public string Name { get; set; }
public ObservableCollection<ChildDirModel> Child { get; set; }
public DirModel()
{
Child = new ObservableCollection<ChildDirModel>();
}
}
public class ChildDirModel
{
public string Name { get; set; }
public ObservableCollection<FileModel> Child { get; set; }
public ChildDirModel()
{
Child = new ObservableCollection<FileModel>();
}
}
public class FileModel
{
public string Name { get; set; }
}
Your application will look like this
I'm having a problem getting the content to display in my program, and I suspect I messed up something relating to the DataContext. The controls I am using come from an extension called Syncfusion (to display graphs) but it could be any other control displaying these items.
MainWindow.xaml.cs:
public MainWindow()
{
InitializeComponent();
ViewModel _viewModel = new ViewModel();
DataContext = _viewModel;
}
ViewModel.cs
public class ViewModel
{
public ObservableCollection<TotalData> TotalDataColl { get; set; }
public ViewModel()
{
TotalDataColl = new ObservableCollection<TotalData>();
var vm = new ChartViewModel
{
Series = new ObservableCollection<SeriesViewModel>
{
new SeriesViewModel{type="Lemons", Items = new ObservableCollection<ItemViewModel>{new ItemViewModel{source = "January", value = 25}, new ItemViewModel{source = "February", value = 35}}},
new SeriesViewModel{type="Oranges",Items = new ObservableCollection<ItemViewModel>{new ItemViewModel{source = "January", value = 22}, new ItemViewModel{source = "February", value = 36}}}
}
};
}
}
MainWindow.xaml
<Grid>
<local:ExtendedChart ItemsSource="{Binding Series}" Margin="0,-38,0,97">
<local:ExtendedChart.ItemTemplate>
<DataTemplate>
<chart:ColumnSeries ItemsSource="{Binding Items}" DependentValuePath="value" IndependentValuePath="source" Title="{Binding type}" />
</DataTemplate>
</local:ExtendedChart.ItemTemplate>
</local:ExtendedChart>
</Grid>
DataClass.cs
public class ChartViewModel : ObservableObject
{
private ObservableCollection<SeriesViewModel> _series;
public ObservableCollection<SeriesViewModel> Series
{
get
{
return _series;
}
set
{
_series = value;
OnPropertyChanged("Series");
}
}
}
public class SeriesViewModel : ObservableObject
{
private ObservableCollection<ItemViewModel> items;
private string _type;
public string type { get { return _type; } set { _type = value; OnPropertyChanged("_type"); } }
public ObservableCollection<ItemViewModel> Items { get { return items; } set { items = value; OnPropertyChanged("Items"); } }
}
public class ItemViewModel : ObservableObject
{
private string _source;
private double _value;
public string Source { get { return _source;} set { _source = value; OnPropertyChanged("Source"); } }
public double Value { get { return _value; } set { _value = value;OnPropertyChanged("Value"); } }
}
ViewModel
public class ViewModel
{
public ObservableCollection<TotalData> TotalDataColl { get; set; }
public ChartViewModel ChartSeriesViewModel { get; set; }
public ViewModel()
{
TotalDataColl = new ObservableCollection<TotalData>();
ChartSeriesViewModel = new ChartViewModel
{
Series = new ObservableCollection<SeriesViewModel>
{
new SeriesViewModel{type="Lemons", Items = new ObservableCollection<ItemViewModel>{new ItemViewModel{source = "January", value = 25}, new ItemViewModel{source = "February", value = 35}}},
new SeriesViewModel{type="Oranges",Items = new ObservableCollection<ItemViewModel>{new ItemViewModel{source = "January", value = 22}, new ItemViewModel{source = "February", value = 36}}}
}
};
}
}
MainWindow.Xaml
<Grid>
<local:ExtendedChart ItemsSource="{Binding ChartSeriesViewModel.Series}" Margin="0,-38,0,97">
<local:ExtendedChart.ItemTemplate>
<DataTemplate>
<chart:ColumnSeries ItemsSource="{Binding Items}" DependentValuePath="value" IndependentValuePath="source" Title="{Binding type}" />
</DataTemplate>
</local:ExtendedChart.ItemTemplate>
</local:ExtendedChart>
</Grid>
Hello I am trying to databind ListBoxes residing inside ItemTemplate of LLS, so far I have seen grouping applied to a template containing only Textblocks, but I need the 'collection' being grouped by. I know my requirements are not that much practical but I am badly in need of it.
MY MODEL
public class ItemViewModel
{
private string _id;
public string ID
{
get
{
return _id;
}
set
{
if (value != _id)
{
_id = value;
NotifyPropertyChanged("ID");
}
}
}
private string _lineOne;
public string LineOne
{
get
{
return _lineOne;
}
set
{
if (value != _lineOne)
{
_lineOne = value;
NotifyPropertyChanged("LineOne");
}
}
}
private string _lineTwo;
public string LineTwo
{
get
{
return _lineTwo;
}
set
{
if (value != _lineTwo)
{
_lineTwo = value;
NotifyPropertyChanged("LineTwo");
}
}
}
}
MY VIEWMODELS
public class GroupedItemViewModel
{
public string Key2
{
get
{
return _key2;
}
set
{
if (value != _key2)
{
_key2 = value;
NotifyPropertyChanged("Key2");
}
}
}
private ObservableCollection<ItemViewModel> _grp;
public ObservableCollection<ItemViewModel> GroupedItems
{
get
{
return _grp;
}
set
{
if (value != _grp)
{
_grp= value;
NotifyPropertyChanged("GroupedItems");
}
}
}
}
public class MainViewModel : ViewModelBase,INotifyPropertyChanged
{
public MainViewModel()
{
this.Items = new ObservableCollection<ItemViewModel>();
}
public ObservableCollection<ItemViewModel> Items { get; private set; }
public ObservableCollection<GroupedItemViewModel> GroupedPhotos
{
get
{
var finalQuery = Items
.GroupBy(category => category.LineOne)
.Select(grouping => new GroupedItemViewModel { Key2 = grouping.Key, GroupedItems = grouping.ToObservableCollection<ItemViewModel>() });
return new ObservableCollection<GroupedItemViewModel>(finalQuery);
}
}
}
MY VIEW - LLS
<Grid x:Name="ContentPanel">
<phone:LongListSelector ItemsSource="{Binding GroupedPhotos}" ItemTemplate="{StaticResource DataTemplate3}" GroupHeaderTemplate="{StaticResource header}"/>
</Grid>
MY VIEW - DATA TEMPLATE OF LLS
<DataTemplate x:Key="DataTemplate3">
<Grid>
<ListBox ItemsSource="{Binding GroupedItems}" ItemTemplate="{StaticResource DataTemplate4}" ItemsPanel="{StaticResource ItemsPanelTemplate2}"/>
</Grid>
</DataTemplate>
MY VIEW - DATA TEMPLATE OF LISTBOX
<DataTemplate x:Key="DataTemplate4">
<Grid>
<TextBlock Text="{Binding LineOne}"/>
</Grid>
</DataTemplate>
MY VIEW - DATA TEMPLATE OF GROUP HEADER
<DataTemplate x:Key="header">
<Grid>
<TextBlock Text="{Binding Key2}"/>
</Grid>
</DataTemplate>
I have a ComboBox in my XAML. It is populated with the following code:
PopulateColors.cs
public class PopulateColors
{
public ObservableCollection<ItemsColors> itemsColors { get; set; }
public PopulateColors()
{
this.itemsColors = new ObservableCollection<ItemsColors>();
this.itemsColors.Add(new ItemsColors{ ItemColumn = "Blue", IdItemColumn = 0 });
this.itemsColors.Add(new ItemsColors{ ItemColumn = "Red", IdItemColumn = 1 });
this.itemsColors.Add(new ItemsColors{ ItemColumn = "Pink", IdItemColumn = 2 });
}
}
public class ItemsColors
{
public string ItemColumn { get; set; }
public int IdItemColumn { get; set; }
}
pagedemo.xaml.cs:
ClothingViewModel ClothVM = null;
public pagedemo()
{
this.comboColors.DataContext = new PopulateColors();
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
ClothVM = new ClothingViewModel();
ClothVM = ClothVM.GetData(1);
this.DataContext = ClothVM ;
navigationHelper.OnNavigatedTo(e);
}
private void SaveButton_Click(object sender, RoutedEventArgs e)
{
string result = ClothVM .Save( ClothVM );
if (result.Contains("OK"))
{
//to do
}
}
pagedemo.xaml (XAML design)
<TextBox x:Name="txtJersey"
Text="{Binding Jersey, Mode=TwoWay}"/>
<ComboBox Name="comboColors"
ItemsSource="{Binding itemsColors}"
DisplayMemberPath="ItemColumn"
SelectedValuePath="ItemColumn"/>
Ok. items are display fine in ComboBox.
QUESTION:
I need to save the selected color in a table of the database, using MVVM pattern. But how? I have this code. But I do not know how to link it with the ComboBox:
Model: Clothing.cs
Public class Clothing
{
public string Color { get; set; }
public string Jersey { get; set; }
}
ViewModel: ClothingViewModel.cs
public class ClothingViewModel : ViewModelBase
{
public string Save (ClothingViewModel cloth)
{
string result = string.Empty;
using (var db = new SQLite.SQLiteConnection(App.DBPath))
{
string change = string.Empty;
try
{
var existing = (db.Table<Clothing>().Where(
c => c.id == 1)).SingleOrDefault();
if (existing!= null)
{
existing.Color = cloth.Color;
existing.Jersey = cloth.Jersey;
int success = db.Update(existing);
}
}
catch
{ }
}
}
private int id = 1;
public int ID
{
get
{ return id; }
set
{
if (id == value)
{ return; }
id= value;
RaisePropertyChanged("ID");
}
}
private string color = string.Empty;
public string Color
{
get
{ return color; }
set
{
if (color == value)
{ return; }
color = value;
isDirty = true;
RaisePropertyChanged("Color");
}
}
private string jersey = string.Empty;
public string Jersey
{
get
{ return jersey; }
set
{
if (jersey == value)
{ return; }
jersey = value;
isDirty = true;
RaisePropertyChanged("Jersey");
}
}
}
Actually, there are plenty of options. Let's demonstrate just a few of them.
1. Use Binding with RelativeSource to find Ancestor with appropriate DataContext
XAML-code:
<!-- Please use Page instead of Window. -->
<Window>
<StackPanel>
<TextBox x:Name="txtJersey"
Text="{Binding Jersey, Mode=TwoWay}"/>
<!-- Use {x:Type Page} instead of {x:Type Window}. -->
<ComboBox Name="comboColors" ItemsSource="{Binding itemsColors}"
DisplayMemberPath="ItemColumn"
SelectedValue="{Binding
RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}},
Path=DataContext.Color}"
SelectedValuePath="ItemColumn" />
</StackPanel>
</Window>
2. Use Binding with ElementName to the UI-element with appropriate DataContext
XAML-code:
<StackPanel>
<TextBox x:Name="txtJersey"
Text="{Binding Jersey, Mode=TwoWay}"/>
<ComboBox Name="comboColors" ItemsSource="{Binding itemsColors}"
DisplayMemberPath="ItemColumn"
SelectedValue="{Binding
ElementName=txtJersey,
Path=DataContext.Color}"
SelectedValuePath="ItemColumn" />
</StackPanel>
3. Use "one" ViewModel that contains another ViewModel
public class ClothingViewModel : ViewModelBase
{
private readonly PopulateColors colors = new PopulateColors();
public PopulateColors Colors
{
get { return this.colors; }
}
...
}
Page:
// This is a Page (Window in case of using WPF).
public class ClothingWindow
{
public ClothingWindow()
{
InitializeComponent();
// Note: no need to set the DataContext for the ComboBox.
DataContext = new ClothingViewModel();
}
}
XAML-code:
<StackPanel>
<TextBox Text="{Binding Jersey, Mode=TwoWay}"/>
<ComboBox ItemsSource="{Binding Colors.itemsColors}"
DisplayMemberPath="ItemColumn"
SelectedValue="{Binding Color}"
SelectedValuePath="ItemColumn" />
</StackPanel>
References
Data Binding (WPF), MSDN.
Data Binding in WPF, John Papa, MSDN Magazine.
im try to do a simple excercise, but, when i test the first part (show person data) dont show me nothing into UI.
I checked the bindings and I guess are okay, too, I do a debug in the click event of the button and get all the data, but the UI does not show me anything.
all proyect here: Less_300kb or:
public class Persona: BindableBase
{
private string _nombre;
public string Nombre
{
get { return _nombre; }
set { _nombre = value;
SetProperty(ref _nombre, value);}
}
private string _apellido;
public string Apellido
{
get { return _apellido; }
set { SetProperty(ref _apellido, value); }
}
private int _cedula;
public int Cedula
{
get { return _cedula; }
set { _cedula = value;
SetProperty(ref _cedula, value);}
}
private string _profesion;
public string Profesion
{
get { return _profesion; }
set { SetProperty(ref _profesion, value); }
}
}
the second class
public class GrupoPersonas
{
public string Profesion { get; set; }
public List<Persona> ListaPersonas { get; set; }
}
the Last class
public class DataSourcePersonas
{
//public List<Persona> ListaPersonas { get; set; }
public ObservableCollection<Persona> ListaPersonas { get; set; }
public void CrearLista()
{
var listaPivote = new ObservableCollection<Persona>()
{
new Persona(){ Profesion="Ingeniero",Apellido="Ruiz Pacheco",Nombre="Juan Carlos"},
new Persona(){ Profesion="Médico", Apellido="Gonzalez Ramírez", Nombre="Miguel"},
new Persona(){ Profesion="Analista", Apellido="Ramirez", Nombre="Angel"},
new Persona(){ Profesion="Enfermero",Apellido="Aldana", Nombre="Cesar"},
new Persona(){ Profesion="Conductor",Apellido="Echeverry", Nombre="Andres"},
new Persona(){ Profesion="Piloto", Apellido="Coronel", Nombre="David"},
new Persona(){ Profesion="Capitán", Apellido="Baracaldo", Nombre="Alejandro"},
new Persona(){ Profesion="Biólogo", Apellido="Palacios", Nombre="Mauricio"},
new Persona(){ Profesion="Físico", Apellido="Botía", Nombre="Oscar"},
new Persona(){ Profesion="Astrónomo",Apellido="Heldford", Nombre="Axwell"}
};
Random genCedula = new Random();
var listaFull = from persona in listaPivote
from persona2 in listaPivote
from persona3 in listaPivote
select new Persona()
{
Cedula = (int)(genCedula.NextDouble() * 999999999),
Nombre = persona.Nombre,
Apellido = persona2.Apellido,
Profesion = persona3.Profesion
};
//ListaPersonas = new List<Persona>(listaFull);
ListaPersonas = new ObservableCollection<Persona>(listaFull);
}
public ObservableCollection<GrupoPersonas> ListaPersonasAgrupada { get; set; }
public void CrearGrupo()
{
var lista = from persona in ListaPersonas
group persona by persona.Profesion into grupo
select new GrupoPersonas()
{
Profesion = grupo.Key,
ListaPersonas = grupo.ToList()
};
ListaPersonasAgrupada = new ObservableCollection<GrupoPersonas>(lista);
}
}
the xaml
<Page.Resources>
<data:DataSourcePersonas x:Key="DataSourcePersonas"
x:Name="DataSourcePersonas"></data:DataSourcePersonas>
<CollectionViewSource x:Key="CvsGruposPersonas" x:Name="CvsGruposPersonas" IsSourceGrouped="True"
Source="{Binding Source={StaticResource DataSourcePersonas}, Path=ListaPersonasAgrupada}"
ItemsPath="ListaPersonas"></CollectionViewSource>
</Page.Resources>
GridView x:Name="gvGroup" ItemsSource="{Binding Source={StaticResource DataSourcePersonas}, Path=ListaPersonas}"
Margin="10,113,10,10">
<GridView.ItemTemplate>
<DataTemplate>
<StackPanel Style="{StaticResource apptile}">
<TextBlock Style="{StaticResource PersonName}" Text="{Binding Nombre}"/>
<TextBlock Style="{StaticResource PersonName}" Text="{Binding Apellido}"/>
<TextBlock Style="{StaticResource PersonCedula}" Text="{Binding Cedula}"/>
<TextBlock Style="{StaticResource PersonProfession}" Text="{Binding Profesion}"/>
</StackPanel>
</DataTemplate>
</GridView.ItemTemplate>
</GridView>
MainPage
private void Button_Click(object sender, RoutedEventArgs e)
{
DataSourcePersonas.CrearLista();
DataSourcePersonas.CrearGrupo();
gvGroup.UpdateLayout();
}
Okay, so what's happening is your GridView is getting the ListaPersonasAgrupada, and then you are changing it, but your GridView doesn't know that it was changed.
You need to have your ViewModel tell your GridView that ListaPersonasAgrupada has changed. You can do this with INotifyPropertyChanged. Or, if you're using MvvmLight, you can use RaisePropertyChanged.
The other option is to re-set the ItemsSource of the GridView, but that will break the binding.