DataTemplate for ListBox element is not binding at all - c#

I have a ListBox element,
which purpose is to show the users the activities,
that are registered on the Database
so that they can choose from them to modify or delete them.
After consulting two very useful answers about using DataContext and DataTemplates,
I decided to implement that knowledge in my project,
unfortunately, it's not working.
When I run it and I select the text on the ListBox,
I only see: DataTemplate templ = new DataTemplate(typeof(Activities));
as its content, and I didn't mark it up as code,
because I want to stress the fact that it appears as a string,
if you will.
I get that there could be more than one workaround for what I'm trying to achieve.
however I really want to understand this, as it appears to be very useful.
Here's the code:
//This is the connection instance to the database
Connection c = new Connection();
DataTemplate templ = new DataTemplate(
typeof(Activities)
);
//The ListActivities method returns
//an ObservableCollection<Activities> list
libTest.DataContext = c.ListActivities(
objSem.getId()
);
libTest.SetBinding(
ItemsControl.ItemsSourceProperty, new Binding()
);
FrameworkElementFactory sp = new FrameworkElementFactory(
typeof(StackPanel)
);
sp.SetValue(StackPanel.OrientationProperty, Orientation.Horizontal);
sp.Name = "myTemplate";
FrameworkElementFactory date = new FrameworkElementFactory(
typeof(Label)
);
date.SetBinding(Label.ContentProperty, new Binding("date"));
sp.AppendChild(date);
FrameworkElementFactory nameAct = new FrameworkElementFactory(
typeof(Label)
);
nameAct.SetBinding(Label.ContentProperty, new Binding("nameAct"));
sp.AppendChild(nameAct);
FrameworkElementFactory descr = new FrameworkElementFactory(
typeof(Label)
);
descr.SetBinding(Label.ContentProperty, new Binding("descr"));
sp.AppendChild(descr);
FrameworkElementFactory quantity = new FrameworkElementFactory(typeof(Label));
quantity.SetBinding(Label.ContentProperty, new Binding("quantity"));
sp.AppendChild(quantity);
templ.VisualTree = sp;
libTest.ItemTemplate = templ;

i dont like code definition for such thing so here is the xaml one
<DataTemplate DataType="{x:Type local:Activities}">
<StackPanel Orientation="Horizontal">
<Label Content="{Binding date}"/>
<Label Content="{Binding nameAct}"/>
<Label Content="{Binding descr}"/>
<Label Content="{Binding quantity}"/>
</StackPanel>
</DataTemplate>
just put this into your resources and all Activities will render like this
pls read something more about binding in WPF, maybe MVVM stuff too. so you would better understand what you need when you do binding with WPF.
a little example
create a class which will be your DataContext and put a public property for your List in it.
public class SampleViewModel
{
public ObservableCollection<Activities> MyActivities {get;set;}
}
xaml.cs: set the DataContext for your View to your Viewmodel class
public partial class SampleWindow : Window
{
private SampleViewModel _data;
public SampleWindow()
{
_data = new SampleViewModel();
InitializeComponent();
this.DataContext = _data;
}
}
xaml: define your Bindings for your controls
<ListBox ItemsSource="{Binding MyActivities}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Label Content="{Binding date}"/>
<Label Content="{Binding nameAct}"/>
<Label Content="{Binding descr}"/>
<Label Content="{Binding quantity}"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
or
<ListBox ItemsSource="{Binding MyActivities}">
<ListBox.Resources>
<DataTemplate DataType="{x:Type local:Activities}">
<StackPanel Orientation="Horizontal">
<Label Content="{Binding date}"/>
<Label Content="{Binding nameAct}"/>
<Label Content="{Binding descr}"/>
<Label Content="{Binding quantity}"/>
</StackPanel>
</DataTemplate>
</ListBox.Resources>
</ListBox>

Related

Set Icon with binding

I'm using Mahapps Metro and Mahapps IconPack.
xmlns:icons="http://metro.mahapps.com/winfx/xaml/iconpacks"
I have a Itemscontrols what works as expected, like this:
<ItemsControl ItemsSource="{Binding MyCollection}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button>
<icons:MaterialDesign Kind="Home"/>
</Button>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
Now I want to set the Icon from the collection for each item.
<ItemsControl ItemsSource="{Binding MyCollection}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button>
<icons:MaterialDesign Kind="{Binding icon}"/>
</Button>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
I have a property which will be added to the collection:
public MahApps.Metro.IconPacks.PackIconMaterialKind MyIcon = MahApps.Metro.IconPacks.PackIconMaterialKind.AbTesting;
If I do so I will get the following error:
Binding' can only be set on a DependencyProperty of a DependencyObject.
I tried to setup the DependencyObject like this:
public static readonly DependencyProperty MyIcon =
DependencyProperty.Register(nameof(MyIcon), typeof(MahApps.Metro.IconPacks.PackIconMaterialKind), typeof(MahApps.Metro.IconPacks.PackIconMaterialKind), new PropertyMetadata(null));
public MahApps.Metro.IconPacks.PackIconMaterialKind myIcon
{
get { return (MahApps.Metro.IconPacks.PackIconMaterialKind)GetValue(dependencyProperty); }
set { SetValue(dependencyProperty, value); }
}
But the GetValue and SetValue are not recognised.
I also tried to set this through a style, but then only the string to the icon will be set as content and not the icon itself.
Can anybody please explain me where I got lost, and how to do this.
Thank you very much.
Thanks for the comments. I was able to figure it out.
I added:
public PackIconMaterialDesign IconMaterialDesign => new PackIconMaterialDesign { Kind = PackIconMaterialDesignKind.AccessAlarm, Height = 30, Width = 30 };
And then I was able to bind it:
<Button Command="{Binding ViewModelRouter}"
CommandParameter="{Binding ViewModelName}"
Style="{StaticResource MenuButton}"
Content="{Binding IconMaterialDesign}" >
Thanks for the comments. I was able to figure it out.
I added:
public PackIconMaterialDesign IconMaterialDesign =>
new PackIconMaterialDesign { Kind =
PackIconMaterialDesignKind.AccessAlarm, Height = 30,
Width = 30 };
And then i was able to bind it:
<Button Command="{Binding ViewModelRouter}"
CommandParameter="{Binding ViewModelName}"
Style="{StaticResource MenuButton}"
Content="{Binding IconMaterialDesign}" >

In wpf Clear ListBox items at Runtime

I am using wpf listbox, i cannot able to clear the list when am calling the reload data function, i just want to reload new data at runtime,while page loading it loads the data correctly, when i refresh the new data is fetched in itemsource i can see that in debug mode, but no new data in listbox, old data remains in the list, i cant even clear, when i call list.items.clear(), i tried lot ways, is there any problem in my XAML binding, the following is my code.
XAML:
<ListBox ItemsSource="{Binding}" HorizontalContentAlignment="Left" x:Name="lstbxindex" Foreground="White" FontSize="20px" Height="400" BorderBrush="#555555" Margin="10,34,16,0" VerticalAlignment="Top" Width="322" Background="#555555" >
<ListBox.ItemTemplate>
<DataTemplate>
<WrapPanel Orientation="Horizontal" Margin="5" >
<StackPanel Orientation="Horizontal">
<TextBlock x:Name="txtblckroundhour" Height="40px" Width="55px" Text="{Binding RoundedHours}" FontSize="14" Background="#555555" Loaded="txtblckroundhour_Loaded" Foreground="White"></TextBlock>
<Label x:Name="items" MouseDoubleClick="items_MouseDoubleClick" Content="{Binding ProjectRow.Name}" Background="#555555" FontSize="20" Loaded="items_Loaded" Visibility="Visible" Margin="35,0,0,0" Width="230" Foreground="White"></Label>
</StackPanel>
<StackPanel Orientation="Vertical">
<ComboBox Height="40px" Width="290" Margin="-230,0,0,0" Loaded="ComboBox_Loaded" Visibility="Hidden" IsEditable="True" FontSize="20" Background="White" Foreground="Black"></ComboBox>
</StackPanel>
<!--<ComboBox x:Name="ComboBox_AddItem" Height="40px" Width="290" Margin="-35,35,0,0" Loaded="ComboBox_AddItem_Loaded" IsEditable="True" FontSize="20" Background="White" Visibility="Hidden" Foreground="Black"></ComboBox>-->
</WrapPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Get the list of values
private List<ProjectInformation> projectInformationList1 = new List<ProjectInformation>();
// Here define the actual binding of the userinterface listbox to the in-memory list of objects.
foreach (DtoProjectsRow row in projectsTable.Rows)
{
projectInformationList1.Add(new ProjectInformation(row));
}
lstbxindex.DataContext = projectInformationList1;
In SO I tried some solution but unfortunately it is not work for me. Last I tried,
XAML.cs page
public static readonly DependencyProperty MyListProperty = DependencyProperty.Register("MyList", typeof(ObservableCollection<String>), typeof(Window));
public ObservableCollection<String> MyList
{
get
{
return (ObservableCollection<String>)GetValue(MyListProperty);
}
set
{
SetValue(MyListProperty, value);
}
}
XAML:
<ListBox ItemsSource="{Binding **ElementName=Window**}" HorizontalContentAlignment="Left" x:Name="lstbxindex" Foreground="White" FontSize="20px" Height="400" BorderBrush="#555555" Margin="10,34,16,0" VerticalAlignment="Top" Width="322" Background="#555555" >
Using this above solution listitems are clear but when pageloading the listboxitems are clear but I don't want to clear the iistboxitems, after updating the values from user it will reload the updated value in listbox.
lstbxindex.ItemsSource = null;
But its not work.For pageload listbox loaded all items,every 15 min interval it will call the load function for firsttime it will reload the updatedvalues but second time it will reload the updated values and previous values remains in listbox again.
I misunderstood initially thinking you were using MVVM, instead you're populating the ListView datasource from code behind.
Your line lstbxindex.DataContext = projectInformationList1; does not set the Data as you'd think. Instead try lstbxindex.DataContext = this; which means you're telling your view to look for the data source in code behind.
As such, I suggest adding using System.ComponentModel; and using BindingList, a comparison is here.
private BindingList<ProjectInformation> projectInformationList1 = new BindingList<ProjectInformation>();
And you just need this once:
foreach (DtoProjectsRow row in projectsTable.Rows)
{
projectInformationList1.Add(new ProjectInformation(row));
}
lstbxindex.DataSource = projectInformationList1;
As mentioned in the comments, if you did not use ItemsSource="{Binding projectInformationList1}" as I suggested in a comment to your question, this is the alternative:
private ObservableCollection<ProjectInformation> projectInformationList1 = new ObservableCollection<ProjectInformation>();
foreach (DtoProjectsRow row in projectsTable.Rows)
{
projectInformationList1.Add(new ProjectInformation(row));
}
lstbxindex.DataContext = projectInformationList1;
You should have a view model class with a collection property, e.g. like this:
public class ViewModel
{
public ObservableCollection<ProjectInformation> Projects { get; }
= new ObservableCollection<ProjectInformation>();
}
Set the DataContext of your Window or Page in XAML like this:
<Window.DataContext>
<local:ViewModel/>
</Window.DataContext>
and bind the ListBox like this:
<ListBox ItemsSource="{Binding Projects}">
...
</ListBox>
To clear all items in the source collection, access the DataContext in code behind:
var vm = (ViewModel)DataContext;
vm.Projects.Clear();
Edit: Instead of assigning the DataContext in XAML, you may as well do it in code behind, even before the Page or Window is initialized:
public MainWindow()
{
DataContext = new ViewModel();
InitializeComponent();
}
Added the line in loadfunction, Initially set null for ItemSource and then set null to the list object
lstbx.ItemsSource=null;
lstbx.Items.Clear();
ProjectInfoList1=null;
it will clear the listboxitems and reload with updated values only.
private BindingList<ProjectInfo> projectInfoList1 = new BindingList<ProjectInfo>();
Public void loadfunction()
{
lstbx.ItemsSource=null;
lstbx.Items.Clear();
ProjectInformationList1=null;
foreach (DtoProRow row in table.Rows)
{
projectInfoList1.Add(new ProjectInfo(row));
}
lstbx.DataContext = projectInfoList1;
}

Bind list to listboxitem in wpf

I'm trying to bind a list to a listbox in WPF. But it doesn't seem to work, I just see nothing on screen.
Here is my code:
WPF
<ListBox x:Name="listBox" HorizontalAlignment="Left" Height="453" VerticalAlignment="Top" Width="119" Margin="0,43,0,0" ItemsSource="{Binding orderlist}">
<ListBoxItem Content="{Binding orderlist.ID}"></ListBoxItem>
</ListBox>
C#
Order order = new Order();
Klantgegevens klantgegevens = new Klantgegevens();
XmlReader rdr = XmlReader.Create(#"C:\Users\Gebruiker\Desktop\EDI\Rekening.xml");
rdr.ReadToFollowing("datum");
order.DatumOntvangst = rdr.ReadElementContentAsString();
rdr.ReadToFollowing("volgnr");
order.Status = "Aangenomen";
order.Opmerkingen = "";
rdr.ReadToFollowing("naam");
order.Afzender = rdr.ReadElementContentAsString();
rdr.ReadToFollowing("naam");
klantgegevens.Naam = rdr.ReadElementContentAsString();
rdr.ReadToFollowing("straat");
klantgegevens.Straat = rdr.ReadElementContentAsString();
rdr.ReadToFollowing("huisnr");
klantgegevens.Huisnummer = rdr.ReadElementContentAsInt();
rdr.ReadToFollowing("plaats");
klantgegevens.Woonplaats = rdr.ReadElementContentAsString();
rdr.ReadToFollowing("postcode");
klantgegevens.Postcode = rdr.ReadElementContentAsString();
rdr.ReadToFollowing("telefoonnr");
klantgegevens.Telefoonnummer = rdr.ReadElementContentAsString();
order.Klantgegevens = klantgegevens;
orderlist.Add(order);
listBox.DataContext = orderlist;
As you probably know, Order is a custom class, and so is Klantgegevens.
I'm pretty new to binding and WPF in general so excuse me for my stupidness :)
You need to set or bind the ItemsSource property of ListView to an IEnumerable. Since you have set the DataContext property to your "orderlist" you should bind the ItemsSource property directly to the DataContext (ItemsSource="{Binding}"). You should also use an ItemTemplate as suggested by Fruchtzwerg :
<ListBox x:Name="listBox" HorizontalAlignment="Left" Height="453" VerticalAlignment="Top" Width="119" Margin="0,43,0,0" ItemsSource="{Binding}">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding ID}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Also note that the DataContext of the ItemTemplate is an item in your ItemsSource, i.e. an Order object in this case. So to bind to the "ID" property of the Order object you use the binding syntax above. "ID" must be a public property of the Order class.
With
<ListBoxItem Content="{Binding orderlist.ID}"></ListBoxItem>
you are adding an item in XAML. But your plan is to create a template to present bound items. The simplest solution is to use
<ListBox x:Name="listBox" DisplayMemberPath="ID"/>
if only one property needs to be presented. Multiple properties can be showed by creating a template like
<ListView x:Name="listBox">
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding ID}" />
<TextBlock Text="{Binding datum}"/>
<!-- ... -->
</WrapPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Furthermore you should use a property like
public ObservableCollection<Klantgegevens> Items { get; } =
new ObservableCollection<Klantgegevens>();
to bind on. Set the DataContext of the whole Window with the ListView to the object, with this property. After that you can bind the ListView with
<ListView ItemsSource="{Binding Items}"/>

Can I swap a buttons content databind to a different databind in code?

I cannot find any examples to make me understand how and if I can change the databind in c# at the click of a button on, in my case a toggleswitch, Basically I have 32 buttons in my app and those 32 buttons act the same but need different text with-in them depending on some toggle switches they are currently databinded so the text can be saved and retrieved from local storage but what values it gets depends on the state of these toggle switches.
So I currently have :
<Button x:Name="_ovButton1" Content="{Binding Source={StaticResource AppSettings}, Path=ovName1_1Value, Mode=TwoWay}" Margin="2,0,250,0" VerticalAlignment="Top" FontSize="14" Height="72" FontWeight="Bold" MouseLeftButtonUp="_ovButton1_MouseLeftButtonUp" MouseLeftButtonDown="_ovButton1_MouseLeftButtonDown" ClickMode="Hover" Hold="_ovButton1_Hold"/>
and I want when a user changes the state of a toggleswitch to change the
{StaticResource AppSettings}, Path=ovName1_1Value, Mode=TwoWay}
to for example:
{StaticResource AppSettings}, Path=ovName1_2Value, Mode=TwoWay}
but I cannot find any example that shows how to do that in c#
what code do I need to do that?
You can specify the target of databinding in code like this:
MyData myDataObject = new MyData(DateTime.Now);
Binding myBinding = new Binding("MyDataProperty");
myBinding.Source = myDataObject;
myText.SetBinding(TextBlock.TextProperty, myBinding);
See more at http://msdn.microsoft.com/en-us/library/ms742863.aspx
-- Edit Note I don't have access to a WP8 Emulator to test this ---
In the view model it looks like this:
public List<string> Members
{
get { return _Members; }
set { _Members = value; OnPropertyChanged(); }
}
public MainVM()
{
// Simulate Asychronous access, such as to a db.
Task.Run(() =>
{
Thread.Sleep(2000);
Members = new List<string>() {"Alpha", "Beta", "Gamma", "Omega"};
});
}
The code behind on the main page sets the datacontext (shared with all the child controls) as such:
public MainWindow()
{
InitializeComponent();
// Set the windows data context so all controls can have it.
DataContext = new MainVM();
}
The Mainpage Xaml to bind to members is like this
<Button Height="30"
Width="80"
Margin="10"
DataContext="{Binding Members}"
Content="{Binding Path=[0] }" />
<Button Height="30"
Width="80"
Margin="10"
DataContext="{Binding Members}"
Content="{Binding Path=[1] }" />
<Button Height="30"
Width="80"
Margin="10"
DataContext="{Binding Members}"
Content="{Binding Path=[2] }" />
<Button Height="30"
Width="80"
Margin="10"
DataContext="{Binding Members}"
Content="{Binding Path=[3] }" />
The result is this visually:
I based this on my blog article Xaml: ViewModel Main Page Instantiation and Loading Strategy for Easier Binding for more info and a fuller example.
I think your best bet is going to be to use a collection of strings and bind to that collection. You can either change the collection when a toggle is switched, or keep 6 collections and bind to the collection that is for the toggle.
Xaml:
<ItemsControl x:Name="Buttons" ItemsSource="{Binding ButtonTextCollection}">
<ItemsControl.ItemsPanel>
<toolkit:WrapPanel/>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button Width="100" Height="70" Content="{Binding}" Click="OnButtonClick"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
Your code-behind would have the event handler for your button click
private void OnButtonClick(object sender, RoutedEventArgs e)
{
var text = ((Button) sender).Content.ToString();
// Send the text
}
Your ViewModel would hold the ButtonTextCollection property and would change based on the toggle.
public ICollection<string> ButtonTextCollection
{
get { return _buttonTextCollection; }
set
{
_buttonTextCollection = value;
OnPropertyChanged("ButtonTextCollection");
}
}
When you want to change the text, you would change the ButtonTextCollection
public void ChangeButtonText()
{
ButtonTextCollection = new Collection<string> {"A", "B",...};
}

binding the xml to same code page

I am trying to bind a XML page to same underlying code page.
<toolkit:ToggleSwitch Foreground="Transparent" Checked="ToggleSwitch_Checked" IsChecked="{Binding Source={StaticResource appSettings}, Path=LockSetting, Mode=TwoWay}">
<toolkit:ToggleSwitch.ContentTemplate>
<DataTemplate>
<StackPanel Orientation="Vertical" DataContext="{Binding}">
<TextBlock Text="locks or unlocks your calender" Style="{StaticResource PhoneTextNormalStyle}"/>
<TextBlock x:Name="statusBox" Text="{Binding stat1}" Style="{StaticResource PhoneTextTitle3Style}" />
</StackPanel>
</DataTemplate>
</toolkit:ToggleSwitch.ContentTemplate>
I have set the data context as
stat1 = "abn";
InitializeComponent();
aps = this.Resources["appSettings"] as AppSettings;
this.colorpicker.Color = Color.FromArgb(aps.ASetting, aps.RSetting, aps.GSetting, aps.BSetting);
ContentPanel.DataContext = this;
But this is not working at all. Any help will be good.
When you write ContentPanel.DataContext = this it implies in this case that the Code-behind of the XAML would be providing context for the data binding. More specifically, when you write {Binding sta1} in the XAML, sta1 must be a property in the code behind. That is, sta1 should be something like that:
public String sta1 { get; set; }

Categories

Resources