XAML Code for TREEVIEW - wpf

Following is the code I wrote for generating treeview hierarchy,
For Each k As KeyValuePair(Of String, GenreSet) In GenreSetDictionary
Dim t As New TreeNodeSet
t.Genre = True
t.Imagepath = k.Value.IconPath
t.Namee = k.Key
Dim pnode As New TreeViewItem
pnode.DataContext = t
pnode.Visibility = True
For Each z As DatabaseDearDataSet.DiskListRow In adpt.GetDataByGenre(t.Namee)
Dim tt As New TreeNodeSet
tt.Genre = False
tt.Imagepath = IconDictionary(z.DiskIcon).IconPath
tt.Namee = z.DiskName
Dim cnode As New TreeViewItem
cnode.DataContext = tt
pnode.Items.Add(cnode)
Next
DisksTreeView1.Items.Add(pnode)
Next
Following is the code I have used in XAML:
<TreeView Height="211" HorizontalAlignment="Left" Margin="19,15,0,0" Name="TreeView1" VerticalAlignment="Top" Width="346">
<TreeView.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Image Source="{Binding ImagePath}" Width="32" Height="32"/>
<TextBlock Text="{Binding Namee}" VerticalAlignment="Center" HorizontalAlignment="Center" />
</StackPanel>
</DataTemplate>
</TreeView.ItemTemplate>
</TreeView>
However, I was not able to get that work, could you please tell me where my XAML went wrong please.

I see few minor mismatches here: the name of the TreeView control (TreeView1 or DisksTreeView1) and the ImagePath property (or Imagepath, c# is sensible to the register of variables).
But the main reason of the incorrect behavior is that the ItemTemplate property is applied to the ItemsSource property, not to the Items property.
Here are two possible ways to correct the code:
1) Fixeing of the data class, item template and binding to the ItemsSource
Create the myObservableCollection private field of the type ObservableCollection(Of TreeNodeSet).
Add to the constructor the line DisksTreeView1.ItemsSource = myObservableCollection
Change the line DisksTreeView1.Items.Add(pnode) to the line myObservableCollection.Add(t).
Add the Disks property to the TreeNodeSet class (the type is ObservableCollection too)
In the xaml replace the line with DataTemplate to the line <HierarchicalDataTemplate ItemsSource="{Binding Disks}"
Change the line pnode.Items.Add(cnode) to the line t.Disks.Add(tt).
2) Using the HeaderTemplate property instead of the ItemTemplate property.
At first, move the DataTemplate to resources and add some key. Then add a similar code near each TreeViewItem in the code-behind:
Dim pnode As New TreeViewItem
pnode.DataContext = t
pnode.Header = t
pnode.HeaderTemplate = Resources("someKey")

Related

selected item from listbox XAML

I am trying to get the selected item from the ListBox using listbox_SelectionChanged() method, but it does not seem to work. Could you tell me what is the best way to get the selected item out of listbox. the code I tried is bellow.
your help much appreciated.
XAML
<ListBox
x:Name="lbSkills"
Grid.Row="1"
Margin="10,0,10,10" SelectionChanged="LbSkills_SelectionChanged">
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch"></Setter>
</Style>
</ListBox.ItemContainerStyle>
<ListBox.ItemTemplate>
<DataTemplate>
<Border BorderThickness="0,0,0,1" BorderBrush="Beige">
<Grid Width="auto" HorizontalAlignment="Stretch">
<TextBlock VerticalAlignment="Center" FontSize="26" Grid.Column="0" Foreground="Black" Text="{Binding SkillDescription}"/>
</Grid>
</Border>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
XAML.cs - I have also tried commented code, but unable to get the selected item
private async void LbSkills_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
//var addedItems = e.AddedItems;
//string selectedSkillString = "None";
//if (addedItems.Count > 0)
//{
// var selectedSkill = addedItems[0];
// selectedSkillString = selectedSkill.ToString();
//}
//lbSkills.SelectedItem.ToString();
MessageDialog msgBox = new MessageDialog(e.AddedItems.ToString());
await msgBox.ShowAsync();
}
First of all check what is the DataConntext or ItemsSource of you ListBox (it have to be an ObservableCollection to avoid the memory leaks).
Check if there is a Binding errors in the Output window.
Check if there is a correcct property to bind to.
Try the solution the next solution:
As I can understand you, the problem is that the added items of event argument doesn't contains the current selected item. But there is no any problem with your code. It returns the actual model (Skill) when I used it. But if you apply ToString() metod on it, you won't get the real model, the result will be just the full name of a class (<Full.Assembly.Path>.<Class_Name>). If you want to get the model instance you have to cast or safely cast the e.AddedItems content or you have to override the ToString() method in your model class. From another hand if you want to get the ListBoxItem itself for some reason try to use the next code:
var listBox = sender as ListBox;
var selected = e.AddedItems.Cast<object>().FirstOrDefault();
var container = listBox.ItemContainerGenerator.ContainerFromItem(selected);
regards

Binding dynamically generated textblock WPF MVVM Light

I am using MVVMM Light WPF and I want to do the following: Generate textboxes dynamically and bind them to a property of a class.
I already have the following but it doesn't show up in my view when running the application.
This is my collection:
private ObservableCollection<Border> _controllekes;
public ObservableCollection<Border> Controllekes
{
get { return _controllekes; }
set
{
_controllekes = value;
RaisePropertyChanged("Controllekes");
}
}
This it my xaml:
<ItemsControl ItemsSource="{Binding Path=Controllekes}">
</ItemsControl>
This is a part where I fill the itemsource "Controllekes":
Controllekes = new ObservableCollection<Border>();
Border border = new Border();
border.BorderThickness = new System.Windows.Thickness(5);
border.BorderBrush = Brushes.AliceBlue;
border.Padding = new System.Windows.Thickness(5);
TextBlock tb = new TextBlock();
tb.Background = Brushes.Red;
Binding nameTextBinding = new Binding("Controllekes");
nameTextBinding.Path = new System.Windows.PropertyPath(this.Dossier.Omschrijving);
nameTextBinding.Mode = BindingMode.OneWay;
//nameTextBinding.Source = this.Dossier.Omschrijving;
tb.SetBinding(TextBlock.TextProperty, nameTextBinding);
border.Child = tb;
this.Controllekes.Add(border);
What it does it creates a border with in this border a textblock where the binding should happen. I whish to bind the property this.Dossier.Omschrijving (Dossier is the class). If I just enter a string in the textbox it works.
In runtime the border gets generated but the textblock remains empty. The object Dossier.Omschrijving contains information.
What do I do wrong?
EDIT:
safe put me in the right direction and the answer of ItemsControl with multiple DataTemplates for a viewmodel made me finish the job :)
through all that and use ItemTemplate
<ItemsControl x:Name="ic">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel>
<CheckBox IsChecked="{Binding yourboolProperty}"/>
<TextBlock Background="Red" Text="{Binding yourStringProperty}"></TextBlock>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
and set ic's ItemsSource to List

wpf binding to string

I have a Movie class with a Dim _characters = New ObservableCollection(of String)
Characters is the associated property to get and set
How can i get characters to show up in the listBox using Binding?
So far i have the following, this isn't working as i don't know what to put instead of ToString.
<ListBox Name="cList" ItemsSource="{Binding Characters}">
<ItemsControl >
<ItemsControl.ItemTemplate >
<DataTemplate >
<TextBox Text="{Binding ToString}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ListBox>
I want them to be editable, hence a textbox.
i tried to bind Characters to TextBox directly, even that didn't work.
Edit :
in the code i have parentGrid1.DataContext = me.movies where
parent grid holds movies.
For those who are experiencing the exception
... binding requires path or xpath ...
You can bind the object directly this way:
<Label Content="{Binding .}" />
Change your TextBox binding to the following. I think it should work:
<TextBox Text="{Binding}"/>
This loads the item itself instead of a property or method output. Since the item is a string it should bind to the strings value.
You cannot perform two-way binding to ObservableCollection<string>. In order to make the strings editable you have to create a class with a string get/set property as the following class Foo:
public class Foo
{
string _text;
public Foo(string text)
{
_text = text;
}
public string Text
{
get { return _text; }
set { _text = value; }
}
}
Your Characters should then be of type ObservableCollection<Foo> and your XAML should be changed so that the textboxes are binding to Foo.Text:
<ListBox ItemsSource="{Binding Characters}" >
<ListBox.ItemTemplate >
<DataTemplate >
<TextBox Text="{Binding Text}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Just remove the ToString portion of the code.
Currently you are telling the program that you want to bind to an object called ToString
I take it that Characters is a public property. Debug and be sure that get is being called for Characters. If you have a the datacontext of the page/window to Movies then you need ItemsSource on the ListBox to be {Binding Path=Characters}

How to add ListBox Items in WPF?

how do I add items to a listbox control by using < ListBox.ItemTemplate> ?
here is the xaml part:
<ListBox HorizontalAlignment="Stretch" Name="ListBox1" VerticalAlignment="Stretch" Margin="0,20">
<ListBox.ItemTemplate>
<DataTemplate>
<Label Content="???????" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
and here is the code for adding items:
private sub Button1_Click() Handles Button1.Click
ListBox1.Items.Add("Hello World")
End Sub
if I click on the buton1, a list item will be added with "??????" - I need to replace the "?????" with {Binding} or something so it can get the value correct value from button1_click ("Hello World")
Yes, just replace it with {Binding}, that alone should do it.
({Binding} binds to the DataContext and the DataContext of the ItemTemplate will be the respective item, if the item is a simple string as in your example that will do, if it is a complex data object you will want to specify a Path to bind to a property of the item)

How do you bind a DataRow to a TextBlock?

I have Window. Window.DataContext = DataRow.
and i have TextBlock.
I need to bind DataRow.Array[0] to the Text property of a TextBlock.
how do I do it?
edit:
<Window x:Class="Client.payment.CheckMore"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:wpf="http://schemas.microsoft.com/wpf/2008/toolkit" Loaded="Window_Loaded" x:Name="p_this">
<DockPanel>
<TextBlock x:Name="p_idCheck" Text="{Binding Path=Array[0]}"/>
</DockPanel>
</Window>
in code: this.DataContext = dateRow.Rows[0];
The Property you're looking for is probably ItemArray. You can bind to it like this, the following ways will give you the same result (if the first Column is named Column1).
The first example binds to the first item in ItemArray
The second example binds to the value of the first Column
The third example binds to the value of the Column named Column1. This is the recommended approach since it will still work even if your Columns change order.
Xaml
<StackPanel>
<TextBlock x:Name="p_idCheck"
Text="{Binding Path=ItemArray[0]}"/>
<TextBlock x:Name="p_idCheck2"
Text="{Binding Path=[0]}"/>
<TextBlock x:Name="p_idCheck3"
Text="{Binding Path=[Column1]}"/>
</StackPanel>
Code behind example
private DataSet m_dataSet = null;
public MainWindow()
{
InitializeComponent();
m_dataSet = new DataSet();
DataTable dataTable1 = new DataTable("Table1");
dataTable1.Columns.Add("Column1", typeof(string));
m_dataSet.Tables.Add(dataTable1);
DataRow dataRow1 = dataTable1.NewRow();
dataRow1["Column1"] = "Column1Value";
dataTable1.Rows.Add(dataRow1);
this.DataContext = dataRow1;
}
<TextBlock Text = "{Binding Array[0]}" ...
works fine if Array is public property.

Resources