WPF binding objects to Listbox, text not appearing - wpf

I searched and could not find an answer to my problem can someone help? I tried to bind a list of objects to a listbox. I have the correct number of items (I can still select them) but I could not see the texts.
My Xaml Code:
<ListBox x:Name="listbox_leave" BorderThickness="0">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding leaveName}" />
<TextBlock Text="{Binding numberOfDays}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
This is backend code:
ObservableCollection<Leave> leavelist = new ObservableCollection<Leave>();
leavelist = DbControl.loadLeaveDetails();
listbox_leave.ItemsSource = leavelist;
and my Leave Class:
class Leave
{
public string leaveName;
public string LeaveName
{
get { return leaveName; }
set { leaveName = value; }
}
public string numberOfDays;
public string NumberOfDays
{
get { return numberOfDays; }
set { numberOfDays = value; }
}
}
When I debug, the ObservableCollection list of Leave has all the correct data, my listbox display blank but it have the correct number of object Leave in it (I could select them) but there is no text displaying. And I have this msg:
System.Windows.Data Error: 40 : BindingExpression path error: 'leaveName' property not found on 'object' ''Leave' (HashCode=44930696)'. BindingExpression:Path=leaveName; DataItem='Leave' (HashCode=44930696); target element is 'TextBlock' (Name=''); target property is 'Text' (type 'String')
System.Windows.Data Error: 40 : BindingExpression path error: 'numberOfDays' property not found on 'object' ''Leave' (HashCode=44930696)'. BindingExpression:Path=numberOfDays; DataItem='Leave' (HashCode=44930696); target element is 'TextBlock' (Name=''); target property is 'Text' (type 'String')
System.Windows.Data Error: 40 : BindingExpression path error: 'leaveName' property not found on 'object' ''Leave' (HashCode=29274103)'. BindingExpression:Path=leaveName; DataItem='Leave' (HashCode=29274103); target element is 'TextBlock' (Name=''); target property is 'Text' (type 'String')
System.Windows.Data Error: 40 : BindingExpression path error: 'numberOfDays' property not found on 'object' ''Leave' (HashCode=29274103)'. BindingExpression:Path=numberOfDays; DataItem='Leave' (HashCode=29274103); target element is 'TextBlock' (Name=''); target property is 'Text' (type 'String')
Can Someone help??

You are trying to bind to the fields (leaveName and numberOfDays) instead of the properties (LeaveName and NumberOfDays), and this is not supported in WPF.
Change it to:
<ListBox x:Name="listbox_leave" BorderThickness="0">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding LeaveName}" />
<TextBlock Text="{Binding NumberOfDays}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Also, you should probably go ahead and make the fields private (leaveName and numberOfDays) instead of public.

Related

Why can't the Grid find the DependencyProperty on the host UserControl? [duplicate]

I try to use binding with an attached property. But can't get it working.
public class Attached
{
public static DependencyProperty TestProperty =
DependencyProperty.RegisterAttached("TestProperty", typeof(bool), typeof(Attached),
new FrameworkPropertyMetadata(false, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault | FrameworkPropertyMetadataOptions.Inherits));
public static bool GetTest(DependencyObject obj)
{
return (bool)obj.GetValue(TestProperty);
}
public static void SetTest(DependencyObject obj, bool value)
{
obj.SetValue(TestProperty, value);
}
}
The XAML Code:
<Window ...>
<StackPanel local:Attached.Test="true" x:Name="f">
<CheckBox local:Attached.Test="true" IsChecked="{Binding (local:Attached.Test), Mode=TwoWay, RelativeSource={RelativeSource Self}}" />
<CheckBox local:Attached.Test="true" IsChecked="{Binding (local:Attached.Test), Mode=TwoWay}" />
</StackPanel>
</Window>
And the Binding Error:
System.Windows.Data Error: 40 : BindingExpression path error: '(local:Attached.Test)' property not found on 'object' ''StackPanel' (Name='f')'. BindingExpression:Path=(local:Attached.Test); DataItem='StackPanel' (Name='f'); target element is 'CheckBox' (Name=''); target property is 'IsChecked' (type 'Nullable`1')
Believe it or not, just add Path= and use parenthesis when binding to an attached property:
IsChecked="{Binding Path=(local:Attached.Test), Mode=TwoWay, RelativeSource={RelativeSource Self}}"
In addition, your call to RegisterAttached should pass in "Test" as the property name, not "TestProperty".
I'd have preferred to post this as a comment on Kent's answer but since I don't have enough rep to do so... just wanted to point out that as of WPF 4.5, adding Path= isn't necessary anymore. However the attached property name still needs to be wrapped with parentheses.
Putting a bracket works. I had to do automation id binding of a parent contentcontrol to a textblock in datatemplate. Automation Id is an attached property.
I put the property in brackets and binding worked.
AutomationProperties.AutomationId="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=ContentControl},Path=(AutomationProperties.AutomationId)}"

Binding in code-behind

I want to bind an IEnumerable to an ItemsControl. Here is the code in XAML that works:
<ItemsControl Name="SearchItemsControl" ItemsSource="{Binding Path=SearchResult}" ScrollViewer.CanContentScroll="True" BorderThickness="0" Background="{StaticResource PopUpContentGradientBrush}" VirtualizingStackPanel.IsVirtualizing="True" >
I want to do it from code-behind, and this is my code:
Binding binding = new Binding("SearchResult");
binding.Source = SearchResult;
And in BeginInvoke of a dispatcher:
SearchItemsControl.SetBinding(ItemsControl.ItemsSourceProperty, binding);
Here's the error I get in the Otput tab of VS:
System.Windows.Data Error: 40 : BindingExpression path error: 'SearchResult' property not found on 'object' ''WhereSelectEnumerableIterator`2' (HashCode=14814649)'. BindingExpression:Path=SearchResult; DataItem='WhereSelectEnumerableIterator`2' (HashCode=14814649); target element is 'ItemsControl' (Name=''); target property is 'ItemsSource' (type 'IEnumerable')
SearchResult is a property in my View-Model, which is of type IEnumerable. The control's name in XAML is SearchItemsControl.
Why is this code not working?
Here's the property:
private IEnumerable<SearchResultModel> _searchResult;
public IEnumerable<SearchResultModel> SearchResult
{
get { return _searchResult; }
set
{
_searchResult = value;
OnPropertyChanged("SearchResult");
}
}
First, SearchResult was ObservableCollection, but the same error appeared and I changed it to IEnumaberable.
you have to remove
binding.Source = SearchResult;
otherwise it mean that your ItemsControl get a new "DataContext" SearchResult and should bind the ItemsSource to a Property SearchResult of your object SearchResult.
edit: the following would work but is not the same as you did in xaml
Binding binding = new Binding(".");
binding.Source = SearchResult;

WPF Data Binding- Binding Obj. inside Obj. to UserControl

I have 2 user controls in MainWindow.xaml, They are SidePannel and Description. I am passing an DictionaryModel Object. In the DictionaryModel object there is a Collection of Words and Another object called SidePannelModel. In the SidePannelModel there is another collection of Words and a string property.
DictionaryModel
public class DictionaryModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public SidePannelModel SideModel { get; set; }
public IEnumerable<WordModel> Language2 { get; set; }
public void ToggleLanguage()
{
var temp = this.Language2;
this.Language2 = this.SideModel.Language1;
this.SideModel.Language1 = temp;
OnPropertyChanged("DictionaryChanged");
}
protected void OnPropertyChanged(string name)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(name));
}
}
SidePannelModel
public class SidePannelModel
{
public IEnumerable<WordModel> Language1 { get; set; }
public string SearchWord { get; set; }
}
I am passing the DictionaryModel to DataContext in MainWindow.xaml.cs.
public partial class MainWindow : Window
{
private DictionaryModel dictionary;
public MainWindow()
{
InitializeComponent();
dictionary = new DictionaryModel
{
SideModel = new SidePannelModel {
SearchWord=null,
Language1 = new List<WordModel>()
{
new WordModel() { Word = "Test1" }
, new WordModel() { Word = "Test2" }
, new WordModel() { Word = "Test3" }
, new WordModel() { Word = "Test4" }
, new WordModel() { Word = "Test5" }
, new WordModel() { Word = "Test6" }
, new WordModel() { Word = "Test7" }
, new WordModel() { Word = "Test8" }
, new WordModel() { Word = "Test9" }
, new WordModel() { Word = "Test10" }
} as IEnumerable<WordModel>
},
Language2 = new List<WordModel>()
{
new WordModel() { Word = "Test1" }
, new WordModel() { Word = "Test2" }
, new WordModel() { Word = "Test3" }
, new WordModel() { Word = "Test4" }
, new WordModel() { Word = "Test5" }
, new WordModel() { Word = "kkkkk" }
, new WordModel() { Word = "Test7" }
, new WordModel() { Word = "Test8" }
, new WordModel() { Word = "Test9" }
, new WordModel() { Word = "Test10" }
} as IEnumerable<WordModel>,
};
this.DataContext = dictionary;
}
}
This is how I pass the Collection of Words and the SidePannelModel to the user controllers in the ManiWindow.xaml
<Window x:Class="ThaiDictionary.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sidePanel="clr-namespace:ThaiDictionary"
Title="MainWindow"
Height="619">
<Window.Resources>
<Style TargetType="{x:Type ToggleButton}"
x:Key="toggleButtonStyle">
<Style.Triggers>
<Trigger Property="IsChecked" Value="True">
<Setter Property="Content" Value="Thai to English" />
</Trigger>
<Trigger Property="IsChecked" Value="False">
<Setter Property="Content" Value="English to Thai" />
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>
<Grid Margin="0,0,2,0">
<DockPanel LastChildFill="True">
<Menu IsMainMenu="True" DockPanel.Dock="Top">
<MenuItem Header="_File" />
<MenuItem Header="_Edit" />
<MenuItem Header="_View" />
<MenuItem Header="_Window" />
<MenuItem Header="_Help" />
</Menu>
<StatusBar Height="22" DockPanel.Dock="Bottom"/>
<sidePanel:SidePanel SideModel="{Binding SidePModel, Mode=TwoWay}" DockPanel.Dock="Left" MinWidth="200" MinHeight="540" Margin="5,5,5,1" Width="196"/>
<DockPanel LastChildFill="True" DockPanel.Dock="Left">
<ToggleButton IsChecked="False" DockPanel.Dock="Top" HorizontalAlignment="Left" Height="30" Width="150" Style="{StaticResource toggleButtonStyle}" Checked="ToggleButton_Checked" Unchecked="ToggleButton_Unchecked">
</ToggleButton>
<sidePanel:Description DockPanel.Dock="Top" WordsList2="{Binding Language2, Mode=TwoWay}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" />
</DockPanel>
</DockPanel>
</Grid>
SideModel is defined in the SidePannel.xaml.cs.
public partial class SidePanel : UserControl
{
public static DependencyProperty SideModelProperty;
static SidePanel()
{
SideModelProperty = DependencyProperty.Register("SideModel", typeof(SidePannelModel), typeof(SidePanel));
}
public SidePanel()
{
InitializeComponent();
}
public SidePannelModel SideModel
{
get
{
return (SidePannelModel)GetValue(SideModelProperty);
}
set
{
SetValue(SideModelProperty, value);
}
}
}
But the SidePanel controller is not loaded with the Words I am expecting.
appropriate part of SidePanel.xaml is given below.
<UserControl x:Class="ThaiDictionary.SidePanel"
x:Name="SidePannelController"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:l="clr-namespace:ThaiDictionary"
mc:Ignorable="d" MinHeight="300" MinWidth="300" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Background="Azure">
<UserControl.Resources>
</UserControl.Resources>
<DockPanel LastChildFill="True" DataContext="{Binding SidePModel}">
<l:SearchTextBox SearchEventTimeDelay="00:00:02.00" Text="{Binding ElementName= SidePannelController, Path= SearchWord, Mode=TwoWay}" DockPanel.Dock="Top" Search="SearchTextBox_Search" HorizontalAlignment="Stretch" Background="Bisque"/>
<ListBox Name="LeftSidePnel1" ItemsSource="{Binding ElementName= SidePannelController, Path= Language1, Mode=TwoWay}" HorizontalAlignment="Stretch"
VerticalAlignment="Stretch" ScrollViewer.CanContentScroll="True" ScrollViewer.VerticalScrollBarVisibility="Visible" ItemTemplate="{DynamicResource WordTemplate}" MinHeight="266" Height="auto" >
<ListBox.Resources>
<DataTemplate x:Key="WordTemplate">
<Label Content="{Binding Word}" HorizontalAlignment="Left" VerticalAlignment="Top" Width="auto"/>
</DataTemplate>
</ListBox.Resources>
</ListBox>
</DockPanel>
But when I run the project I can not see the words loaded in to the Sidepanel usercontrol. What is wrong with this code. I can not find a way out here. Can you give me some quick help.
Edit:
I have followed the naming conventions and changed the SidePannel.xaml.cs.
Binding error:
System.Windows.Data Error: 4 : Cannot find source for binding with reference 'ElementName=SidePanelController'. BindingExpression:Path=SearchWord; DataItem=null; target element is 'SearchTextBox' (Name=''); target property is 'Text' (type 'String')
System.Windows.Data Error: 4 : Cannot find source for binding with reference 'ElementName=SidePanelController'. BindingExpression:Path=Language1; DataItem=null; target element is 'ListBox' (Name='LeftSidePnel1'); target property is 'ItemsSource' (type 'IEnumerable')
I have added the full SidePanel.xaml and I have changed the ElementName to SidePannelController as in the xaml file. But it still not getting loading the words
New Edit:
System.Windows.Data Information: 41 : BindingExpression path error: 'SearchWord' property not found for 'object' because data item is null. This could happen because the data provider has not produced any data yet. BindingExpression:Path=SideModel.SearchWord; DataItem='SidePanel' (Name='SidePannelController'); target element is 'SearchTextBox' (Name=''); target property is 'Text' (type 'String')
System.Windows.Data Information: 20 : BindingExpression cannot retrieve value due to missing information. BindingExpression:Path=SideModel.SearchWord; DataItem='SidePanel' (Name='SidePannelController'); target element is 'SearchTextBox' (Name=''); target property is 'Text' (type 'String')
System.Windows.Data Information: 21 : BindingExpression cannot retrieve value from null data item. This could happen when binding is detached or when binding to a Nullable type that has no value. BindingExpression:Path=SideModel.SearchWord; DataItem='SidePanel' (Name='SidePannelController'); target element is 'SearchTextBox' (Name=''); target property is 'Text' (type 'String')
System.Windows.Data Information: 10 : Cannot retrieve value using the binding and no valid fallback value exists; using default instead. BindingExpression:Path=SideModel.SearchWord; DataItem='SidePanel' (Name='SidePannelController'); target element is 'SearchTextBox' (Name=''); target property is 'Text' (type 'String')
System.Windows.Data Information: 41 : BindingExpression path error: 'Language1' property not found for 'object' because data item is null. This could happen because the data provider has not produced any data yet. BindingExpression:Path=SideModel.Language1; DataItem='SidePanel' (Name='SidePannelController'); target element is 'ListBox' (Name='LeftSidePnel1'); target property is 'ItemsSource' (type 'IEnumerable')
System.Windows.Data Information: 20 : BindingExpression cannot retrieve value due to missing information. BindingExpression:Path=SideModel.Language1; DataItem='SidePanel' (Name='SidePannelController'); target element is 'ListBox' (Name='LeftSidePnel1'); target property is 'ItemsSource' (type 'IEnumerable')
System.Windows.Data Information: 21 : BindingExpression cannot retrieve value from null data item. This could happen when binding is detached or when binding to a Nullable type that has no value. BindingExpression:Path=SideModel.Language1; DataItem='SidePanel' (Name='SidePannelController'); target element is 'ListBox' (Name='LeftSidePnel1'); target property is 'ItemsSource' (type 'IEnumerable')
Thanks
Language1 and SearchWord are not properties on your UserControl, they're properties on your UserControl.SideModel property.
So change your bindings to include SideModel in your Path property, so it correctly binds to SidePannelController.SideModel.Language1 (or SearchWord), like this:
ItemsSource="{Binding ElementName=SidePannelController, Path=SideModel.Language1}"
But I suspect you're not showing your actual XAML, because your binding error says "Cannot find source for binding", which means it can't find an element named SidePannelController in the VisualTree (since ElementName specifies the source to use for the binding).
If that's the case, you can try using a RelativeSource binding to find the UserControl instead of ElementName
ItemsSource="{Binding Path=SideModel.Language1,
RelativeSource={RelativeSource AncestorType={x:Type l:SidePanel}}"
I don't know what DictionaryModel is.
Maybe a typo, but it's possible you have an extra }, in MainWindow.xaml.cs right before:
Language2 = new List<WordModel>()
That would mean that Language2 is not a member of dictionary.SideModel, but instead is another, separate element of the collection (a sibling property of SideModel?)
However, in MainWindow.xaml, you are Binding to Language2 inside of a binding to SideModel. Since Language2 isn't a child of SideModel, XAML can't resolve the binding.

WPF binding to obfuscated object can't find the property

I am trying to bind a ComboBox to the named cells of a SpreadsheetGear worksheet.
SpreadsheetGear is an obfuscated assembly, so that i my first guess.
<ComboBox Width="200" x:Name="comboBox" IsEditable="True" ItemsSource="{Binding Names, Mode=OneWay}">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}"/>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
and the view-model propery is
private IWorksheet worksheet;
public IWorksheet Worksheet
{
get { return worksheet; }
private set { SetField(ref worksheet, value, () => Worksheet); OnPropertyChanged(() => Names); }
}
public IEnumerable<IName> Names
{
get { return Worksheet.Names.Cast<IName>(); }
}
I am getting the following error in my Output window
System.Windows.Data Error: 40 : BindingExpression path error: 'Name' property not found on 'object' ''ᜪ' (HashCode=1500138080)'. BindingExpression:Path=Name; DataItem='ᜪ' (HashCode=1500138080); target element is 'TextBlock' (Name=''); target property is 'Text' (type 'String')
I've tried returning Worksheet.Names directly, which doesn't inherit from Enumerable but DOES provide GetEnumerator(). That yielded the same error.
Any ideas?
Without more code, it's hard to say, but I'll take a random guess: Is IName an internal interface? Most code obfuscators will only mangle internal/private/protected classes/enums/interfaces...

WPF Attached Property Data Binding

I try to use binding with an attached property. But can't get it working.
public class Attached
{
public static DependencyProperty TestProperty =
DependencyProperty.RegisterAttached("TestProperty", typeof(bool), typeof(Attached),
new FrameworkPropertyMetadata(false, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault | FrameworkPropertyMetadataOptions.Inherits));
public static bool GetTest(DependencyObject obj)
{
return (bool)obj.GetValue(TestProperty);
}
public static void SetTest(DependencyObject obj, bool value)
{
obj.SetValue(TestProperty, value);
}
}
The XAML Code:
<Window ...>
<StackPanel local:Attached.Test="true" x:Name="f">
<CheckBox local:Attached.Test="true" IsChecked="{Binding (local:Attached.Test), Mode=TwoWay, RelativeSource={RelativeSource Self}}" />
<CheckBox local:Attached.Test="true" IsChecked="{Binding (local:Attached.Test), Mode=TwoWay}" />
</StackPanel>
</Window>
And the Binding Error:
System.Windows.Data Error: 40 : BindingExpression path error: '(local:Attached.Test)' property not found on 'object' ''StackPanel' (Name='f')'. BindingExpression:Path=(local:Attached.Test); DataItem='StackPanel' (Name='f'); target element is 'CheckBox' (Name=''); target property is 'IsChecked' (type 'Nullable`1')
Believe it or not, just add Path= and use parenthesis when binding to an attached property:
IsChecked="{Binding Path=(local:Attached.Test), Mode=TwoWay, RelativeSource={RelativeSource Self}}"
In addition, your call to RegisterAttached should pass in "Test" as the property name, not "TestProperty".
I'd have preferred to post this as a comment on Kent's answer but since I don't have enough rep to do so... just wanted to point out that as of WPF 4.5, adding Path= isn't necessary anymore. However the attached property name still needs to be wrapped with parentheses.
Putting a bracket works. I had to do automation id binding of a parent contentcontrol to a textblock in datatemplate. Automation Id is an attached property.
I put the property in brackets and binding worked.
AutomationProperties.AutomationId="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=ContentControl},Path=(AutomationProperties.AutomationId)}"

Resources