I feel really stupid for asking this but I have been thrashing for over 8 hours. How do I get the Selected Item to show its text in my WPF combo box when selected?
Above is an option dialog that allows users to select and configure the available tournament displays. The problem is the selected combo box item shows the UserControl instead of the Display name.
On Window Loaded:
//_displayer is a private member populated using MEF
//[ImportMany(typeof (IDisplayer))]
//private IEnumerable<IDisplayer> _displayers;
DisplayTypeComboBox.ItemsSource = _displayers;
The ComboBox Xaml:
<ComboBox
Name="DisplayTypeComboBox"
Grid.Column="1"
Grid.ColumnSpan="2"
Grid.Row="1"
IsEditable="False"
SelectionChanged="DisplayTypeComboBox_SelectionChanged">
<ComboBox.ItemTemplate>
<DataTemplate>
<ComboBoxItem Content="{Binding DisplayerName}" />
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
The IDisplayer:
public interface IDisplayer
{
string DisplayDataLocation { get; set; }
string DisplayerName { get; }
string DisplayerDescription { get;}
bool WatcherEnabled { get; }
UserControl View { get; }
string DisplayerImageLeft { get; set; }
string DisplayerImageRight { get; set; }
void Update();
}
I don't even want to think about how many hours I have spent trying to solve what should be a simple problem. Why is it so hard to get your selected text to appear as the selected value? I give up, WPF you have beat me into submission. I changed the control to a list box it takes up more room to display the selectable Items but at least it works.
<ListBox
Name="DisplayTypeComboBox"
Grid.Column="1"
Grid.ColumnSpan="2"
Grid.Row="1"
SelectionChanged="DisplayType_SelectionChanged">
<ListBox.ItemTemplate>
<DataTemplate>
<Label Content="{Binding DisplayerName}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
I encountered the same thing. Took me a while too. :(
You should have used the ItemContainerStyle and not ItemTemplate.
Because ComboBox wraps the internal items with a ComboBoxItem - you basically wrapped the ComboBoxItem with another one.
Check what DisplayerName member actually contains. Most likely it contains the UserControl name instead of the Display name.
Try using a TextBlock to bind to the DisplayerName instead of a ComboboxItem. I believe that when you set the itemsource, the combo control will wrap the items inside comboboxitems controls automatically.
Edit: I misunderstood your question. Try setting the SelectionBoxItemTemplate.
Related
I do want to create a listview which consists of many items of an own class. One of the properties is a text which can contain one or more links in it. Normally I use a textblock with a binding on Text to get this content displayed.
Now I do want those text being parsed for links and then dynamically make those links clickable. I found quite some code like Add hyperlink to textblock wpf on how to create a textblock with hyperlinks so I would be fine - but the WPF binding is available on the Text property so this doesn't help me in the end.
So is there a way for binding for a list of items (ObservableCollection or similar) in a listview to have clickable links within text?
Thx in advance
Sven
I have a simple solution.
Using the DataTemplate, you could specify an template for a class, say LinkItem which contains your text, and a hyper-link.
public class LinkItem
{
public string Text { get; set; }
public string Hyperlink { get; set; }
public LinkItem(string text, string hyperlink)
{
Text = text;
Hyperlink = hyperlink;
}
}
// XAML Data template
<DataTemplate DataType="{x:Type HyperlinkDemo:LinkItem}">
<TextBlock>
<TextBlock Text="{Binding Text}" Margin="1" />
<Hyperlink>
<TextBlock Text="{Binding Hyperlink}" Margin="1" />
</Hyperlink>
</TextBlock>
</DataTemplate>
// List box definition
<ListBox ItemsSource="{Binding LinkItems}" />
Nice and simple. Just add a bunch of LinkItem to your LinkItems collection and you will get some nice mix of text and hyperlink in your list box.
You could also throw in a command in the LinkItem class to make things a little more interesting and bind the command to the hyperlink.
<Hyperlink Command="{Binding HyperlinkCommand}"> ....
This is a very basic question. I have a grid, whose data context is bound to a entity framework service. I simply bound the context to service and I can see the data that is getting bound properly. Now, I want to change couple of coulmns to special controls. Like one column has true or false value and that column I want to display a radio button. One column is date value, I want to display date control. How would one go about doing it?
Thanks.
I'm not exactly sure how to do the Radio Button portion of this, but something like this may get you started:
<ListBox x:Name="LayoutRoot" ItemsSource="{Binding Collection}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Text}"/>
<CheckBox Content="True" IsChecked="{Binding Checked, Mode=TwoWay}"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
In this case, you would have a checkbox being bound to the boolean value. I'm not exactly sure what you are using for a date control, but you should be able to place that in the stackpanel also and bind it to the dateproperty of your item.
In the above example, 'Collection' is an observable collection of 'MyObject' which is shown below:
MyObject.cs
public class MyObject
{
public string Text { get; set; }
public bool Checked { get; set; }
public bool InverseChecked { get; set; }
public DateTime Date { get; set; }
}
I also understand that you were using a grid, and I'm showing a ListBox. Not sure if this would work for you, but this is how we've approached it in the past.
Hope this helps!
I'm new to WPF and before I dive in solving a problem in completely the wrong way I was wondering if WPF is clever enough to handle something for me.
Imagine I have a collection containing objects. Each object is of the same known type and has two parameters. Name (a string) and Picked (a boolean).
The collection will be populated at run time.
I would like to build up a UI element at run time that will represent this collection as a series of checkboxes. I want the Picked parameter of any given object in the collection updated if the user changes the selected state of the checkbox.
To me, the answer is simple. I iterate accross the collection and create a new checkbox for each object, dynamically wiring up a ValueChanged event to capture when Picked should be changed.
It has occured to me, however, that I may be able to harness some unknown feature of WPF to do this better (or "properly"). For example, could data binding be employed here?
I would be very interested in anyone's thoughts.
Thanks,
E
FootNote: The structure of the collection can be changed completely to better fit any chosen solution but ultimately I will always start from, and end with, some list of string and boolean pairs.
I would strongly recommend the ItemsControl, its behaviour is as close as you can get to the ASP.Net repeater control so it is very flexible.
Declare the item control as:
<ItemsControl Name="YourItemsControl"
ItemsSource="{Binding Path=YourCollection}"
ItemTemplate="{StaticResource YourTemplate}">
</ItemsControl>
Then you can use the datatemplate to organise the data into a display format for the user
<DataTemplate x:Key="ProjectsTemplate">
<StackPanel Margin="0,0,0,10">
<Border CornerRadius="2,2,0,0" Background="{StaticResource ItemGradient}" d:LayoutOverrides="Width, Height">
<local:ItemContentsUserControl Height="30"/>
</Border>
...
Useful ItemsControl Links
http://drwpf.com/blog/itemscontrol-a-to-z/
http://www.galasoft.ch/mydotnet/articles/article-2007041201.aspx
I hope this helps you.
You can use Data Templates. Here's a good post about it.
This is exactly the kind of scenario WPF simplifies. Event-handlers- bah! Data-binding and data templates make this a cinch. I have constructed an example illustrating how you can do this.
Here is the code-behind, which declares a class to represent your items- PickedItem. I then create a collection of these items and populate it with some samples.
public partial class DataBoundCollection : Window
{
public DataBoundCollection()
{
Items = new ObservableCollection<PickedItem>();
Items.Add(new PickedItem("Item 1"));
Items.Add(new PickedItem("Item 2"));
Items.Add(new PickedItem("Item 3"));
InitializeComponent();
}
public ObservableCollection<PickedItem> Items
{
get;
set;
}
}
public class PickedItem
{
public PickedItem(string name)
{
Name = name;
Picked = false;
}
public string Name
{
get;
set;
}
public bool Picked
{
get;
set;
}
}
Now, let's look at the XAML mark-up for this window:
<Window x:Class="TestWpfApplication.DataBoundCollection"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="DataBoundCollection" Height="300" Width="300"
DataContext="{Binding RelativeSource={RelativeSource Self}}">
<Grid>
<ListBox ItemsSource="{Binding Items}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<CheckBox IsChecked="{Binding Picked}" Margin="5"/>
<TextBlock Text="{Binding Name}" VerticalAlignment="Center"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
I create a ListBox to hold the items, and bind its ItemsSource property to the collection I created in the code-behind. Then, I provide the ListBox with an ItemTemplate, which determines how each PickedItem will be rendered. The DataTemplate in this case is as simple as a check-box and some text, both bound to the member variables on PickedItem. Now, when I check any of these items, the data in the underlying collection is modified, in real-time, with no event handlers needed. Ta-da!
alt text http://img405.imageshack.us/img405/1083/databoundcollection.png
I have a simple ComboBox in my Silverlight 3 application. I want to populate it from an ObservableCollection. The list holds a class that has a Name(string), and a Selected(bool) property. The combo box has as many items as I have in the list, but I cannot seem to get the list data to appear.
Any help would be appreciated.
<ComboBox x:Name="cmbCategory" Grid.Column="3">
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Name}"/>
<CheckBox IsChecked="{Binding Selected}"/>
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
...
private class cmbCategoryClass
{
public string Name { get; set; }
public bool Selected { get; set; }
}
private ObservableCollection<cmbCategoryClass> _categories;
....
cmbCategory.DataContext = _categories;
cmbCategory.ItemsSource = _categories;
I can't tell from your code if this is a Codebehind or a ViewModel. I am guessing that you are actually populating the _categories list in code so that it contains at least one cmbCategoryClass object. Try removing the line that sets the DataContext to _categories as your ItemsSource may be looking for a _categories property on the DataContext Check the Output window in Visual Studio when running in debug mode for clues to data binding failures.
I am stucked at the part where I have to bind a collection to a dynamic usercontrol. Scenario is something like this.
I have a dynamic control, having a expander , datagrid, combobox and textbox, where combox and textbox are inside datagrid. There are already two collections with them. One is binded with combobox and another is binded with datagrid. When the item is changes in combox its respective value is set to its respective textbox, and so on. and this pair of value is then set to the collection binded with datagrid. A user can add multiple items.
Now the main problem is that all these things are happening inside a user control which is added dynamically, that is on button click event. A user can add desired numbers of user controls to the form.
problem is coming in this situtaion. Say I have added 3 controls. Now in 1st one if i add a code to the collection then it gets reflected in the next two controls too, as they are binded with same collection.
So, I want to know is there anyway to regenrate/rename the same collection so that the above condition should not arise.
It's hard to answer your question without seeing the bigger picture, however I have a feeling you are going about this the wrong way. It appears that you are adding instances of your user control directly from code. Instead of doing that, you should create some kind of ItemsControl in your XAML, and in its ItemTemplate have your user control. Bind that ItemsControl to a collection in your view model, and only manipulate that collection.
You should not be referring to visual controls in your view model or code behind. Whenever you find yourself referencing visual elements directly from code, it should raise a warning flag in your mind "Hey! There's a better way than that!"...
Example:
The view model:
public class ViewModel
{
public ObservableCollection<MyDataObject> MyDataObjects { get; set; }
public ViewModel()
{
MyDataObjects = new ObservableCollection<MyDataObject>
{
new MyDataObject { Name="Name1", Value="Value1" },
new MyDataObject { Name="Name2", Value="Value2" }
};
}
}
public class MyDataObject
{
public string Name { get; set; }
public string Value { get; set; }
}
The window XAML fragment containing the list box and the data template:
<Window.Resources>
...
<DataTemplate x:Key="MyDataTemplate">
<local:MyUserControl/>
</DataTemplate>
</Window.Resources>
...
<ListBox ItemsSource="{Binding MyDataObjects}"
ItemTemplate="{StaticResource MyDataTemplate}"
HorizontalContentAlignment="Stretch"/>
The user control:
<UniformGrid Rows="1">
<TextBlock Text="{Binding Name}"/>
<TextBlock Text="{Binding Value}" HorizontalAlignment="Right"/>
</UniformGrid>