i have a problem with binding an ObservableCollection in XAML
the class :
[DataContract]
public class Result
{
[DataMember]
public string title { get; set; }
[DataMember]
public string href { get; set; }
[DataMember]
public string ingredients { get; set; }
[DataMember]
public string thumbnail { get; set; }
}
the Observable Collection :
private ObservableCollection<Result> resultTest;
the XAML code for binding :
<ListView Name="RecipeListView"
ItemsSource="{Binding resultTest}">
<ListView.ItemTemplate>
<DataTemplate x:DataType="data:Result">
<StackPanel Orientation="Vertical">
<TextBlock Name="RecipeTitleTextBlock"
Text="{Binding title}"
Foreground="Black"
FontSize="24">
</TextBlock>
<Image Name="RecipeImage"
Source="{Binding thumbnail}"
Width="45"
Height="45">
</Image>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Everything seems to be correct as application launches, but there is no content visible that I was binding to.
Thanks you guys for any help.
The issue is you're declaring "resultTest" as a "filed", not a property.
However, the binding system uses reflection to look for property, it does not look for "field".
Changing your resultTest declaration to property would solve the issue.
public ObservableCollection<Result> resultTest {get; private set;}
Also, make sure you have the DataContext properly set with xaml or code-behind like
this.DataContext = this
or
this.DataContext = new ViewModel()
Depending on what your DataContext really is.
My full MainWindow.cs looks like below, and the ListView binding works.
public sealed partial class MainPage : Page
{
public ObservableCollection<Result> resultTest { get; private set; }
public MainPage()
{
resultTest = new ObservableCollection<Result>();
resultTest.Add(new Result() { title = "Hello" });
resultTest.Add(new Result() { title = "World" });
this.DataContext = this;
this.InitializeComponent();
}
}
If you have your datacontext set (i.e. in your code behind have datacontext=this or if you are using mvvm have your datacontext set in your window like this
<Window.DataContext>
<local:MainViewModel/>
</Window.DataContext>
And if you have your collection property setup like
public ObservableCollection<Result> resultTest {get;set;}
as Szabolcs Desi suggested then I would try removing the x:Datatype="data:Result" on your DataTemplate. I tested the code you have minus that and it works for me.
Sorry for this dumb question , the problem was I was using a static method that returned an ObservableCollection to a variable. I thought I should remove it to a void function and fill the collection by foreach inside. Everything in xaml was right.
Related
At the moment i try, to build something like that with WPF ! Screenshot: http://i.imgur.com/5G6xBTu.png
I have a ObservableCollection with my "Wecker" Objects. I want to dynamicly add items to the listbox with DataBinding that looks like in the Screenshot. Every try failed so far. What do i need to set in the XAML File??
public static ObservableCollection<Wecker> WeckerCollection = new ObservableCollection<Wecker>();
public ObservableCollection<Wecker> MyWeckerCollection
{
get { return WeckerCollection; }
}
Wecker Class
public class Wecker
{
public ArrayList dayOfWeek { get; set; }
public DateTime Alarm { get; set; }
public bool activated { get; set; }
public bool loop { get; set; }
public int maxRunTime { get; set; }
public int id { get; set; }
public bool schlummern { get; set; }
public bool antiStandby { get; set; }
public bool activateMonitor { get; set; }
public string fileName { get; set; }
public string Mp3 { get; set; }
public string Message { get; set; }
public bool ShowMessage { get; set; }
public int volume { get; set; } }
I tryed that last time:
<ListBox HorizontalAlignment="Left" Height="392" VerticalAlignment="Top" Width="431" Margin="15,89,0,0" ScrollViewer.VerticalScrollBarVisibility="Visible" ItemsSource="{Binding MyWeckerCollection}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<CheckBox IsChecked="{Binding activated, Mode=TwoWay}" />
<Label Content="{Binding Alarm}" />
<Label Content="{Binding dayOfWeek}" />
<Label Content="{Binding Message}" />
<Label Content="{Binding Mp3}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
I suspect you have not set the DataContext
In the ctor set the DataContext
this.DataContext = this;
or you can do it in XAML in the Window (top) section
DataContext="{Binding RelativeSource={RelativeSource self}}"
If you had set the DataContext then that should work
Are you sure it is in the Windows section
Try (but Path is the default property so that should not be a problem)
ItemsSource="{Binding Path=MyWeckerCollection}"
This may be your problem - public static?
What is the purpose of public static here?
public static ObservableCollection<Wecker> WeckerCollection = new ObservableCollection<Wecker>();
If you want to use a backing property then do it like this
private ObservableCollection<Wecker> myWeckerCollection = new ObservableCollection<Wecker>();
public ObservableCollection<Wecker> MyWeckerCollection
{
get { return myWeckerCollection ; }
}
It sounds like your DataContext is set incorrectly.
You say you are binding the DataContext to {Binding RelativeSource={RelativeSource Self}}, however that just binds the DataContext to the UI object itself.
For example,
<Window DataContext="{Binding RelativeSource={RelativeSource Self}}">
would set the DataContext to the Window object, however the class Window does not have a property called MyWeckerCollection, so your binding would fail.
If you had
<local:MyCustomWindow DataContext="{RelativeSource={RelativeSource Self}}">
and MyCustomWindow has a property called MyWeckerCollection, then it would work.
I also see your comment here which states:
I am not getting any Data at all and i checked the object, "WeckerCollection" it has Data BEFORE setting it as the DataContext
This leads me to believe that either
A) MyWeckerCollection is not a UI control, in which case you need to update your DataContext binding to something other than Self so it correctly binds to your object containing MyWeckerCollection instead of to the UI object.
B) Or this comment can be read as you are setting the DataContext to MyWeckerCollection itself, and of course the class ObservableCollection<Wecker> does not itself have a property called MyWeckerCollection, so the binding would fail.
So the root cause of your problem is the DataContext is not being set correctly.
Unfortunately, the information you provided is not enough for us to help to identify the correct way to set the DataContext, however if you can provide us with more information I'd be glad to help you out.
Often Visual Studio's binding errors and/or Debug mode is enough to point you in the right direction for fixing the DataContext, or there are some 3rd party tools out there like Snoop which I'd highly recommend for debugging binding errors.
Also if you're new to WPF (which it sounds like you are), and are struggling to understand the purpose of the DataContext and how it works, I'd suggest a blog article of mine written for beginners: What is this "DataContext" you speak of?. Its very important that you understand the DataContext if you are going to be working with WPF. :)
Try to add the ItemSource to your ListBox and change the Xaml like this :
Code behind :
this.YourList.ItemsSource = WeckerCollection;
Xaml :
<ListBox HorizontalAlignment="Left" Height="392" VerticalAlignment="Top" Width="431" Margin="15,89,0,0" ScrollViewer.VerticalScrollBarVisibility="Visible">
I have user control:
<UserControl>
<TextBox Name="TB1"/>
<TextBox Name="TB2"/>
</UserControl>
Code behind:
public partial class MyControl : UserControl
{
public TwoStrings TsObj { get; set; }
public MyControl()
{
InitializeComponent();
}
}
Where
public class TwoStrings
{
string S1 { get; set; }
string S2 { get; set; }
}
How to bind TsObj.S1 to TB1.Text and TsObj.S2 to TB2.Text with minimal code changes? TwoStrings should not be changed. Updates on object should reflect on control. Code example please.
There's a lot of resources about wpf/silverlight databinding on the internet, even here in stackoverflow. But long story short, you can simply do this:
<UserControl>
<TextBox Name="TB1" Text="{Binding S1}" />
<TextBox Name="TB2" Text="{Binding S2}"/>
</UserControl>
public partial class MyControl : UserControl
{
public TwoStrings TsObj { get; set; }
public MyControl()
{
InitializeComponent();
this.DataContext = TsObj = new TwoStrings();
}
}
EDIT: Note that if you change properties via code in the TwoStrings instance, that will be not reflected in the textboxes, because you'll need to implement INotifyPropertyChanged interface in TwoStrings (which is the ViewModel - VM in the MVVM pattern) to get two way databinding. Otherwise, you'll get only one way databinding from your textbox to the properties on the datacontext (TwoString)
I was trying to get it working for few days.
What is wrong in this code?
This is my window XAML:
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Rapideo_Client"
x:Class="Rapideo_Client.MainWindow"
Title="NVM" SnapsToDevicePixels="True" Height="400" Width="625">
<Window.Resources>
<DataTemplate x:Key="linksTemplate" DataType="DownloadLink">
<StackPanel Orientation="Vertical">
<TextBlock Text="{Binding Path=Name}" FontWeight="Bold"></TextBlock>
<Label Content="{Binding Path=SizeInMB}"/>
<Label Content="{Binding Path=Url}"/>
</StackPanel>
</DataTemplate>
</Window.Resources>
<ListView ScrollViewer.HorizontalScrollBarVisibility="Disabled"
ScrollViewer.VerticalScrollBarVisibility="Visible"
x:Name="MainListBox"
ItemTemplate="{DynamicResource linksTemplate}">
</ListView>
</Window>
This is my class:
class Rapideo
{
(...)
public List<DownloadLink> Links { get; private set; }
(...)
}
This is my item:
class DownloadLink
{
public string Name { get; private set; }
public string Url { get; private set; }
public DateTime ExpiryDate { get; private set; }
public float SizeInMB { get; private set; }
public int Path { get; private set; }
public string Value { get; private set; }
public LinkState State { get; set; }
public enum LinkState
{
Ready, Downloading, Prepering, Downloaded
}
public DownloadLink(string name, string url, DateTime expiryDate, float sizeInMB, int path, string value, LinkState state)
{
Name = name;
Url = url;
ExpiryDate = expiryDate;
SizeInMB = sizeInMB;
Path = path;
Value = value;
State = state;
}
}
This is my binding:
RapideoAccount = new Rapideo();
MainListBox.ItemsSource = RapideoAccount.Links;
Later in the code I populate that list in RapideoAccount.Links.
But nothing is showing in ListView.
List View is always empty.
Where is mistake in that code?
Yes, it should be an ObservableCollection<DownloadLink> if you're planning on adding to it AFTER you have setup the ItemsSource. If the list is preloaded and you won't be changing it, List<T> would have worked.
Now I do think that
MainListBox.ItemsSource = RapideoAccount.Links;
is still technically a binding. But what you are probably thinking of is binding via the DataContext rather than directly (al la MVVM style). So that'd be:
RapideoAccount = new Rapideo();
this.DataContext = RapideoAccount;
Then in your window, you'd bind your ItemSource like this:
<Window
...
<ListView ScrollViewer.HorizontalScrollBarVisibility="Disabled"
ScrollViewer.VerticalScrollBarVisibility="Visible"
x:Name="MainListBox"
ItemsSource="{Binding Links}"
ItemTemplate="{DynamicResource linksTemplate}">
</ListView>
</Window>
First off, you should use an ObservableCollection<DownloadLink> rather than a List<DownloadLink> if you're planning on making changes to the list after setting up the binding.
Second of all, just to be clear:
MainListBox.ItemsSource = RapideoAccount.Links;
is not a binding. You're just setting the property. That will work for certain scenarios, but its not really a binding like we normally talk about in WPF.
I think that Links needs to be an ObservableCollection, not a List.
I have a UserControl in Silverlight. This UserControl looks like this:
<TextBlock Text="{Binding Path=OrderDate}" />
<TextBlock Text="{Binding Path=ShipDate}" />
I have a class that is defined as follows:
public class MyViewModel : ViewModel
{
public string Description { get; set; }
public string Origin { get; set; }
public SlipDetails Details { get; set; }
}
This view model is populated and in the code-behind of my UserControl. I then use this.DataContext = myViewModel; to set the UserControl's DataContext. My problem is, I want to use relative binding in my details grid. I would like to be able to set the DataContext of "detailsGrid" in the XAML to the Details property. Is there a way to do this?
Thanks
I assume that the OrderDate and ShipDate are part of the SlipDetails class?
In that case, you can bind to those fields by using
<TextBlock Text="{Binding Path=Details.OrderDate}" />
<TextBlock Text="{Binding Path=Details.ShipDate}" />
I am a WPF newcomer, and I've been searching for two days with no luck. I have a WPF window that has several text box controls, and a single object with some properties. This object is passed to the codebehind of my WPF window in it's constructor:
public partial class SettingsDialog : Window
{
public SettingsObject AppSettings
{
get;
set;
}
public SettingsDialog(SettingsObject settings)
{
this.AppSettings = settings;
InitializeComponent();
}
}
The SettingsObject looks something like this (simplified for clarity):
public class SettingsObject
{
public string Setting1 { get; set; }
public string Setting2 { get; set; }
public string Setting3 { get; set; }
public SettingsObject()
{
this.Setting1 = "ABC";
this.Setting2 = "DEF";
this.Setting3 = "GHI";
}
}
And my WPF window (simplified):
<Window x:Class="MyProgram.SettingsDialog"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
DataContext="{Binding Source=AppSettings}">
<Grid>
<TextBox Name="Setting1Textbox" Text="{Binding Path=Setting1}"></TextBox>
<TextBox Name="Setting2Textbox" Text="{Binding Path=Setting2}"></TextBox>
<TextBox Name="Setting3Textbox" Text="{Binding Path=Setting3}"></TextBox>
</Grid>
</Window>
How do you acheive two-way binding in this situation? I've tried what you see above (and so much more) but nothing works!
Have you set the DataContext property of the window to your instance of AppSettings?
public SettingsDialog(SettingsObject settings)
{
InitializeComponent();
//While this line should work above InitializeComponent,
// it's a good idea to put your code afterwards.
this.AppSettings = settings;
//This hooks up the windows data source to your object.
this.DataContext = settings;
}