So I searched in this forum but couldn't find the anwser...
I'm Binding my combobox to a list of users. But when I want to type in it for example a name, some wierd stuff is comming out.
XAML Code:
<ComboBox Name="UserLoginCmbBox" Width="100" IsEditable="True" SelectionChanged="UserLoginCmbBox_SelectionChanged">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Login}"/>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
Code Behind Code:
var users = new List<User>{...} //initialization
UserLoginCmbBox.ItemsSource = users;
When I'm typing in the box only string I can get is:
System.Data.Entity.DynamicProxies.User_FE59351B6479342209B496E7D3C3B877DDC51FE15279FFFEF899A5012F85FCBA
I found out that this is what ToString() method returns, but what if I want to use the same list for expamle in another ComboBox where I want to choose the Name or something else?
How can I modify SelectionItemBox? Cause when I tried to use the SelectionItemBoxTemplate to write my own template, an error occured (SelectionItemBoxTemplate has only getter).
Try to set the DisplayMemberPath property to "Login":
<ComboBox Name="UserLoginCmbBox" Width="100" IsEditable="True" SelectionChanged="UserLoginCmbBox_SelectionChanged" DisplayMemberPath="Login" />
Related
I have a class PricingData and PricingSchedule. Where PricingSchedule is a List<> inside PricingData class. I want to bind data of this class to UWP controls.
Sample code is available to download here : https://github.com/jigneshdesai/SampleOfBindingIssue1.git
How Code looks: i have a start page(mainpage) that hosts ListView control, Listview has PricingUserControl within it. PricingUserControl looks like this
<TextBlock x:Name="lblPriceHeader" Text="{Binding PricingTitle}" Margin="0,0,50,0" />
<ComboBox x:Name="cbPriceValueList" ItemsSource="{x:Bind dpl}" DisplayMemberPath="PriceValue" SelectedValuePath="PriceValue" SelectedValue="{Binding DisplayPricing}" />
<ListView x:Name="lbPriceChangeSchedule" ItemsSource="{Binding PricingScheduleList}">
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel>
<StackPanel Orientation="Horizontal">
<ComboBox x:Name="cbSchedulePriceValueList" ItemsSource="{x:Bind dpl}" DisplayMemberPath="PriceValue" SelectedValuePath="PriceValue" />
<TextBlock Text="{Binding SchedulePricingTimeZone }" />
</StackPanel>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
What i want to achieve: Combobox should populate a list of values (eg. 1USD, 2USD, 3USD etc.). Then when you provide List of records from database, the listbox will repeat PricingUserControl and combobox within it should set its value property (SelectedValue) as per record.
Issue:
ComboBox x:Name="cbPriceValueList" uses x:bind dpl where dpl is a local variable of PricingUserControl. It populates the list properly. The trouble is ComboBox x:Name="cbSchedulePriceValueList" it also has x:bind dpl but during compilation it display error "Invalid binding path 'dpl' : Property 'dpl' not found on type 'DataTemplate'."
I am wondering why x:bind dpl does not work at this point. ?
I have now realized that your problem is in fact that you need to reach to a Page property from within the DataTemplate, so here is a updated answer.
You cannot use x:Bind if you need to access an outside element's property from within a DataTemplate. Instead, you can use classic {Binding} expression. First add a name to your page:
<Page
...
x:Name="Page">
And now refer to this name from within the DataTemplate:
<ComboBox
x:Name="cbSchedulePriceValueList"
ItemsSource="{Binding ElementName=Page, Path=dpl}"
DisplayMemberPath="PriceValue"
SelectedValuePath="PriceValue" />
Original answer
To be able to use x:Bind inside of a DataTemplate, you must specify the data type the individual items of the control will have, using x:DataType. Suppose your PricingScheduleList is a List<MyApp.Models.MyType>, then you will first need to add this XML namespace to the <Page> element:
xmlns:models="using:MyApp.Models"
And then set the x:DataType attribute as follows:
<DataTemplate x:DataType="models:MyType">
...
</DataTemplate>
You can confirm this works by the fact that IntelliSense should now suggest you the properties of MyType when you start writing the x:Bind expression.
By checking your code, the reason why SelectedValue does not take effect is when you choose the item from ComboBox, you didn't notify your DisplayPricing to change. So you need to implement INotifyPropertyChanged interface in your PricingData. Do the same behavior in PricingSchedule.
public class PricingData : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged = delegate { };
......
public string DisplayPricing
{
get => $"{PricingValue} {PricingCurrency}";
set
{
var sp = value.Split(' ');
PricingValue = sp.First();
PricingCurrency = sp.Last();
OnPropertyChanged();
}
}
public void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
PScheduleUserControl.xaml:
<ComboBox x:Name="cbPriceValueList" ItemsSource="{x:Bind myList}" DisplayMemberPath="PriceValue" SelectedValuePath="PriceValue" SelectedValue="{Binding DisplayPricing,Mode=TwoWay}" />
I'm having trouble simply showing the contents of my List in the ComboBox using Caliburn.micros BindableCollection. I get three blank options, but when I chose one of them I get the correct value back so I know it's working. Obviously I would also like to see what it is I'm choosing.
I've tried creating a local string and having it = myList[i] in a for loop. I've even created a random string and tried binding it to my TextBlock using the same naming convention, but I just can't get it to work. I won't add that here since it doesn't work. Hopefully one of you can nudge me in the right direction. I'm new to Caliburn, MVVM, binding, etc....
public List<string> languages = new List<string> {"ENGLISH", "SPANISH", "CHINESE"};
public BindableCollection<string> Language { get; set; }
public SettingsViewModel()
{
Language = new BindableCollection<string>();
for (int i = 0; i < languages.Count; i++)
{
Language.Add(languages[i]);
}
}
//XAML Code\
<ComboBox ItemsSource="{Binding Language}">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding LanguageOptions}" />
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
The problem lies in the following line.
<TextBlock Text="{Binding LanguageOptions}" />
The property Language is BindableCollection of string. It doesn't have a sub-property called LanguageOptions.
You could instead use the following
<ComboBox ItemsSource="{Binding Language}">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding}" />
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
Or to make it even more simpler, you could avoid the ItemTemplate. For example,
<ComboBox ItemsSource="{Binding Language}"/>
That would help you fix the Combo Box.
I've a combobox in WPF with 4 static values in it:
<ComboBox
SelectedValue="{Binding Source={x:Static properties:Settings.Default},
Path=KeyModifier, Mode=TwoWay}">
<ComboBoxItem>Alt</ComboBoxItem>
<ComboBoxItem>Shift</ComboBoxItem>
<ComboBoxItem>Ctrl</ComboBoxItem>
<ComboBoxItem>Win</ComboBoxItem>
</ComboBox>
I want to connect the selected value of this combobox with a simple string property in the user settings. That works half way: The selected value is perfectly written to Settings.Default.KeyModifier ... But after restarting the application the selected value of the combobox is not set ... despite that all other controls (Edits, Checkboxes) binded the same way on other properties are set correctly.
Is there some mystery on filling a combobox with values from a binded property?
Or do I have to do the whole selection process on startup manually in code behind?
Since you don't add strings, but ComboBoxItems to your ComboBox, you would also have to set its SelectedValuePath property:
<ComboBox SelectedValuePath="Content"
SelectedValue="{Binding Source={x:Static properties:Settings.Default},
Path=KeyModifier, Mode=TwoWay}">
<ComboBoxItem>Alt</ComboBoxItem>
<ComboBoxItem>Shift</ComboBoxItem>
<ComboBoxItem>Ctrl</ComboBoxItem>
<ComboBoxItem>Win</ComboBoxItem>
</ComboBox>
Alternatively add strings to the ComboBox, and use SelectedItem instead of SelectedValue:
xmlns:sys="clr-namespace:System;assembly=mscorlib"
...
<ComboBox SelectedItem="{Binding Source={x:Static properties:Settings.Default},
Path=KeyModifier, Mode=TwoWay}">
<sys:String>Alt</sys:String>
<sys:String>Shift</sys:String>
<sys:String>Ctrl</sys:String>
<sys:String>Win</sys:String>
</ComboBox>
Note also that since WPF 4.5 you may write the Binding like this:
SelectedItem="{Binding Path=(properties:Settings.Default).KeyModifier, Mode=TwoWay}"
Have you saved the settings after you change the values? Settings.Default.Save()
In my WPF application I have an Observablecollection "CollOfPersons" of Persons, where each Person Object has a property "NotesOnPerson" of type
List<Notes>
(among other properties). Now I bind "CollOfPersons" to a listbox lb in code via
lb.ItemsSource = CollOfPersons;
Now I have set up a template how to display a person, namely I wrap each person in a 'Expander' and display the basic properties (e.g., Name, Age) in Expander.header, and this works fine, e.g.,
<Expander.Header>
<StackPanel Orientation="Horizontal">
...
<TextBlock Text="{Binding Path=Name}"/>
...
</StackPanel>
</Expander.Header>
However, now I'd like to bind the NotesOnPerson list of notes to the Expander.Content. But since this is again a list of varying size I don't know how to do it. Same strategy as above does not work, because I don't know the name of the Expander (as I knew the name 'lb' of the big listbox in which all the stuff is). Something like
<Expander.Content>
<ListBox ItemTemplate="{StaticResource NoteTemplate}"
ItemsSource="{Binding Path=NotesOnPerson}"/>
</Expander.Content>
doesn't seem to work. I seem to be confused about code and XAML binding. How should I solve this?
Is this what you're looking for?
<Expander.Content>
<ListBox ItemTemplate="{StaticResource NoteTemplate}"
ItemsSource="{Binding NotesOnPerson}"/>
</Expander.Content>
I'm not familiar with the Expander, but since NotesOnPerson is (presumably) a property of Person and not of Name, that's the syntax you should use. (the Path= is optional, since just putting it in like that is another way to declare the Path)
To begin I would like to apologize for my english which is far from perfect (its not my native language...).
I've a problem related to databinding in my XAML code. I've a combox which is supposed to list all graphical nodes that I drop on a custom canvas. My graphical nodes are referenced in a list graphCanvas.uinodes , and each node has a name. And that's what I want to show in my combobox.
So I tried something like this:
<ComboBox ItemsSource="{Binding ElementName=graphCanvas, Path=uinodes/name}"
Height="23" HorizontalAlignment="Left" Name="comboBox1"
VerticalAlignment="Top" Width="71" Foreground="Black" />
But even after drawing nodes on my canvas my combox is empty...
Any clue?
Thanks.
A binding using ElementName finds the WPF element with that name. I doubt that you've subclassed Canvas and added a uinodes property to it, which is the only way that Path would find something even if the path syntax were correct, which it's not.
If you look in the Output window when you run your program, you'll see an error message that tells you why the binding isn't working. That's a start.
But even then, you won't get what you want with this approach. What you probably want looks more like:
<ComboBox ItemsSource="{Binding ElementName=graphCanvas, Path=uinodes}"
DisplayMemberPath="name"/>
or even
<ComboBox ItemsSource="{Binding ElementName=graphCanvas, Path=uinodes}">
<ComboBox.ItemTemplate>
<TextBlock Text="{Binding name}"/>
</ComboBox.ItemTemplate>
</ComboBox>
Your binding (specifically the Path assignment) looks wrong. Assuming uinodes is an Enumerable of some sort it looks as though you are trying to bind to the `name' property of the collection, which does not exist. Try this:
ItemsSource="{Binding ElementName=graphCanvas, Path=uinodes}" DisplayMemberPath="name"
As an aside, you can use the output window to see any binding errors.