Reapplying template for ListBox item programatically - c#

Basically, I have a list of colors and a defined datatemplate for listbox item:
<DataTemplate x:Key="colorItemDataTemplate">
<Border x:Name="borderInner" BorderBrush="Black" BorderThickness="1" Background="{Binding Brush}" Width="11" Height="11" />
</DataTemplate>
Now, when I add a bunch of items into the listbox and then set the ListBox.ItemsSource property to my List, the listbox is filled correctly.
There is also a slider with its appropriate event handler. Within the event handler, Brush property of one of the items from the listbox is changed. Since the appearance of the item depends on the Brush Property, listbox should reflect the change.
I could reset the ItemsSource property, but then all items have their templates applied and with more than 200 items in the listbox, this is pretty slow.
So, is there any way to refresh the template for only one item from the listbox?
Thanx

I'm not sure I follow. If you've bound the Background to the property, changing the property should automatically udpate the background of the ListBoxItem. If you're not seeing that, make sure you are either using a DependencyProperty or implementing INotifyPropertyChanged.

You could use a binding converter. In the converter class you could have some logic like
(pseudo-code)
if (ListBoxItem.IsSelected)
return SpecialColorFromSlider
else
return NormalListBoxColor

Related

How to properly bind to element property in WPF

I have little problem with binding. I have stackpanel in my xaml which has some elements in children collection. Second i have textblock which shows count of elements in stackpanel. It is done by binding that way
<TextBlock Text="{Binding Children.Count, ElementName=CommentsContainer, Mode=OneWay, StringFormat=({0})}" />
<StackPanel x:Name="CommentsContainer"></StackPanel>
It works fine for first-time but if is something added to stackpanel children collection dinamically textblock text is not updated. I mean that collection count does not implement inotifypropertychange, but how do something like this properly?
You asked "how [to] do something like this properly". The WPF way of doing it would be to have a collection of items implemented as a property on your Window or ViewModel or whatever, then bind an ItemsControl to that collection.
For example, if you had a collection of strings:
public ObservableCollection<string> MyItems { get; private set; }
// elsewhere in the same class...
MyItems = new ObservableCollection<string>();
MyItems.Add("first");
MyItems.Add("second");
MyItems.Add("etc");
ObservableCollection<T> is a good collection class to use for WPF as notification of any changes made to the collection (such as adding or removing items) will be pushed to any observers of the collection (such as WPF's binding system).
To see these items in your View (eg. Window, UserControl, etc), you would use a control that can display a list of items (one derived from ItemsControl) and bind that control to the list property, like so:
<Window ... >
<StackPanel>
<ItemsControl ItemsSource="{Binding MyItems}" />
<TextBlock Text="{Binding MyItems.Count}" />
</StackPanel>
</Window>
ObservableCollection<T> does implement INotifyPropertyChanged so the Count property will always reflect the actual number of items in the list.
You don't have to have a list of strings of course, they could be any kind of object. Similarly, you don't have to use an ItemsControl but could use something like a ListBox or ListView instead (they both derive from that base control class). Furthermore, you might want to look into data templating as this can be used to change the visual appearance of the items in the ItemsControl.

Overwrite ListBoxitem?

I'm new to WPF and I have this ListBox which I want to instantiate with a specific ListBoxItem, so the user knows what to do with the ListBox.
<ListBox Name="DbListBox"
Grid.Column="3"
HorizontalAlignment="Left"
Height="246"
Margin="0,99,0,0"
Grid.Row="1"
VerticalAlignment="Top"
Width="211"
SelectionMode="Single"
SelectedItem="{Binding Path=selectedDB,Mode=TwoWay}"
AllowDrop="True"
Drop="DbListBox_Drop">
<ListBoxItem Name="ListBoxItem" FontStyle="Italic">Drag .db file here or add below</ListBoxItem>
</ListBox>
Then I have some code which adds a collection of items to the ItemsSource of this ListBox, but I can't do that since the ItemsSource is not empty
DbListBox.ItemsSource = DbCollection;
My question is, how can I start up the ListBox with the item inserted first, and then when DbCollection is added to it, it simply overwrites the first ListBoxItem?
When using WPF properly, we'd normally have something like this, where a collection property would be data bound to the ListBox.ItemsSource property:
<ListBox ItemsSource="{Binding SomeCollectionProperty}" />
Once we have this XAML, we don't need to touch the ListBox again, as we can add or remove items from the data bound collection and they will magically appear (or disappear) from the ListBox:
SomeCollectionProperty.Add(new SomeDataType());
SomeCollectionProperty.Remove(someItemFromCollection);
The SomeDataType used here is up to you... it depends on what you want to display in your items. If it was just a plain string for example, then you could simply do this to add your initial item into the collection:
SomeCollectionProperty.Add("Drag .db file here or add below");
If you wanted to make that item look different to the others then you'd need to data bind a custom class that has a Text property and FontStyle property for example. You could data bind these properties in a DataTemplate to design each item to be exactly as you want it. However, that's a completely different question.
To find out more about these things, you can read the Data Binding Overview and Data Templating Overview page on MSDN.

Binding ListBoxItem properties when ListBox is bound to ObservableCollection

I have a ListBox bound to an ObservableCollection:
<ListBox ItemsSource="{Binding ObservableCollectionOfFoos}" />
The ObservableCollection contains instances of Foo, Foo implements INotifyPropertyChanged.
I'm trying to bind properties of the ListBoxItems to properties of Foo.
Here is what I tried:
<DataTemplate DataType="{x:Type local:Foo}" >
<TextBlock Content="{Binding PropertyOfFoo}" Background="{Binding AnotherPropertyOfFoo}"/>
</DataTemplate>
this works, but, the problem is that I only have access to the properties of the TextBlock and not the containing ListBoxItem, so, for example, Background only changes the color around the text and not the whole entry. I have a feeling I'm using the wrong tool for the job here.
a point in the right direction would be very appreciated.
The DataTemplate specifies the template (UI presentation) of the content of the list box item. What you need to style is the item container itself which can be done via the ItemContainerStyle property of the ListBox.

Binding Listbox SelectedItems to a Slider in WPF

I am relatively new to WPF, but can you provide an example of how to bind a slider value to a selected item in a listbox. Ideally, as the user moves the slider, the onscreen item changes dynamically as the slider value changes. From reading, I understand that you need to use an attached property or value converter since we are binding different types of values. If so, can you provide a simple example of the most efficient method.
Thank you.
Not sure if this really is the question, but in case you mean to move the selected item through the ListBox items you could directly bind the SelectedIndex of the ListBox to the Slider Value:
<StackPanel>
<ListBox SelectedIndex="{Binding Value, ElementName=slider}">
<ListBoxItem>1</ListBoxItem>
<ListBoxItem>2</ListBoxItem>
...
<ListBoxItem>10</ListBoxItem>
</ListBox>
<Slider Name="slider" Minimum="0" Maximum="9"/>
</StackPanel>
Of course you would have to adjust the Slider's Maximum value to the actual number of items minus one.

unable to add textboxes to listbox

hi I want to add textboxes to a listbox with everyclick on the add button.
so here are my codes
this.ListBox1.Controls.Add(TB);//TB is the name of my TextBox and it has been defined and initialized
I even tried to use Addat
there are no errors but it doesnt work
myYou don't want to add ListBox. Rather, add an object and define a default template for this object using a TextBlock.
So you define your local Namespace
xmlns:local="clr-namespace:MyNameSpace"
in the ressources you define your DataTemplate
<DataTemplate DataType="{x:type local:MyObjectType}">
<TextBlock Text="{Binding ThePropertyIWant}" />
</DataTemplate>
And in your code you just add object of type MyObjectType to your ListBox.
But even better, you add your objects to an ObservableCollection(Of MyObjectTYpe) and you bind that collection to your listBox. So when you add objects to the collection, the display is automatically updated.
Instead of using a ListBox you can use ListView, ListView has the ability to add custom column types
http://www.codeproject.com/Articles/9188/Embedding-Controls-in-a-ListView
http://weblogs.asp.net/scottgu/archive/2007/08/10/the-asp-listview-control-part-1-building-a-product-listing-page-with-clean-css-ui.aspx

Categories

Resources