I have a small custom control which downloads & displays a contacts image. It ensures that only 1 image is being downloaded at a time by adding itself to a static queue of images awaiting to be downloaded.
It is possible to get quite long contact lists. So I want it to only enter the download queue when it actually becomes visible on the screen (there's a default image).
I've tried placing the logic in the Loaded event, overriding OnRender and the IsVisibleChanged event, but none seem to give me what I want.
any suggestions?
D.R
Edit:
This is a WPF Application, sorry for not mentioning before...
Some system controls (like ListView) have property "VirtualMode" if you set it to true and handle RetrieveVirtualItem event. This event invokes for items which are visible currently and you have to fill those items with data(images) you want. So that you don't need to fill all items at once.
Have you considered using a PriorityBinding in order to provide that functionality?
<DataTemplate DataType="{x:Type vm:MyViewModel}">
<StackPanel Orientation="Horizontal">
<Image>
<Image.Source>
<PriorityBinding FallbackValue="{StaticResource ImgDownloading}">
<Binding Path="ImageSource" IsAsync="True" />
</PriorityBinding>
</Image.Source>
</Image>
<Label Content="{Binding Name}" />
</StackPanel>
</DataTemplate>
Related
What I am trying to do is create a ComboBox where at the top there is a textbox that I can type into to filter the items within the ComboBox. Here is a an example of what I mean:
I need to do this using an MVVM approach. I am not sure how to go about this or how to overwrite the style to do so. I have looked on google for several solutions but none of them are quite exactly what I need. I am pretty sure once I have the style created I can figure out the filtering portion within my view model.
Any help would be appreciated.
Use IsTextSearchEnabled from the ComboBox control like this:
<ComboBox IsTextSearchEnabled="True" IsTextSearchCaseSensitive="True or False depending on your scenario" />
In my projects, when I do something like this, I add a TextBox as the first item in the dropdown content template, with a presenter following it of the items that need to be data-bound.
<ComboBox>
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBox Text="{Binding Path=FilteredText"} Mode="TwoWay"/>
<ListBox ItemSource="{Binding Path=ItemsForBinding}" Mode="TwoWay" NotifyOnSourceUpdated="True" />
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
And in your view-model, make sure that NotifyOnProperyChanged is enabled for the FilteredText property when it is updated, it will trigger the "removal" of the bound-items, I usually use ObservableCollection, but I know ListCollectionView has capabilities to filter and notifies the UI when the collection changes. You can even find a 3rd party text AutoCompleteBox ( I use Telerik,) and it would allow you to prepopulate the terms in the "textbox" that you want the user to be able to filter.
I need really efficient control in WPF that could depict up to tousands coloured Text.
Such control responsibility would be similar to Visual Studio Output.
Additionally it must be really efficient because I is supposed to to depict thousands of messages.
Any time new message appears then it should auto scroll to buttom
I used ListBox:
<ListBox Name="ListBoxMessages" ItemsSource="{Binding ObservableMessages}" VerticalAlignment="Stretch" VirtualizingStackPanel.IsVirtualizing="True" >
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Info}" Foreground="{Binding Foreground}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
ObservableMessages is of type: ObservableCollection of messages which contains info and colour.
It quite ok but when I tried to add autoscroll to button on each new item added to collection then it occurs to be really inefficient.
Thread.Sleep(5) helps a little bit but I am not sure if I want to use such workaround.
I investigated WPF RichTextBox so far but it seems really inefficient:
- I tried many solutions related to RichText box and it did not met my expectations.
- another solution would be to create my own control
Could you recommend any solution?
Observable collection is filled up very fast from different threads like this:
public void ProcessNotificationMessage(Message message)
{
Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() => ObservableMessages.Add(message)));
// Thread.Sleep(5);
}
How can i mark menuitem in Application Bar. I want to get, for example, this:
You can change the template of the MenuItem.Header, as described in this tutorial. For example:
<toolkit:ContextMenuService.ContextMenu>
<toolkit:ContextMenu>
<toolkit:MenuItem Header="AddItem"/>
<!-- a templated menu item -->
<toolkit:MenuItem>
<toolkit:MenuItem.Header>
<StackPanel Orientation="Horizontal">
<TextBlock Text="Delete Item"/>
<Image Source="Images/appbar.delete.rest.png"/>
</StackPanel>
</toolkit:MenuItem.Header>
</toolkit:MenuItem>
</toolkit:ContextMenu>
</toolkit:ContextMenuService.ContextMenu>
I'd say it can't be done. The menu items are just calls to functions and can do nothing but show the corresponding text and call the corresponding method when activated. I've found some examples of people hacking extra functionality into them (updating the text or changing the function calls, to some extent), but nothing beyond that would be possible.
Notice that what you can do with the AppBar is limited by the functionality offered by IApplicationBar and, in your case, ApplicationBarMenuItem. And none of them expose anything even close to your requirements.
You can, however, enable and disable menu items, although I don't think that's what you want.
I have a list box in WPF which displays the status of a number of worker threads. Included in the display is a progress bar.
It turns out that progress bars have an issue (defect?): the "Maximum" value is a dependency property, but the progress bar does not update when this property changes.
Somebody encounted a similar problem in this question. The suggested solution is to add a handler to the progress bar that deals with the dependency property changing.
But my progress bar is created by the WPF framework through a data template. (See code below) How could I attach a handler to these dynamically created progress bars?
Or, is there another way to solve this problem?
<DataTemplate x:Key="DataTemplateTransferWorker">
<Border Style="{StaticResource TransferWorker}" Height="Auto">
<StackPanel Orientation="Vertical">
<TextBlock Style="{StaticResource ItemHeader}">Transfer Worker</TextBlock>
<TextBlock Style="{StaticResource FieldValue}" Text="{Binding StatusDescription}" />
<!-- Note that the maximum comes from a changing property. -->
<ProgressBar
Margin="6, 3, 6, 3"
Height="12"
Orientation="Horizontal"
Background="Transparent"
Maximum="{Binding ServerJob.FileSize, Mode=OneWay}"
Value="{Binding BytesUploaded, Mode=OneWay}" />
Later Edit
It turns out that it's not as simple as the Maximum binding value being broken, because there are working examples where progress bars dynamically updates perfectly well.
It wasn't an INotifyPropertyChanged issue. I was notifying of any changes to the ServerJob property, (but not the ServerJob.FileSize property which is constant for each server job.) I also put a breakpoint on ServerJob.FileSize.get, and the framework was indeed querying the filesize in response to the property changed notification.
I also added two TextBlocks to the control, bound to ServerJob.FileSize and BytesUploaded respectively. And they updated exactly as they should.
But for some reason, as soon as the BytesUploaded value became non-zero the progress bar would zoom to 100%.
I've worked around the problem by adding a new property "PercentageComplete" which calculates the progress, and that way I can keep the maximum at a constant value of 100.
I tried creating an application with a ProgressBar in a DataTemplate whose Maximum is bound to a changing property. Like Greg Sansom i do not encounter any problem, i suppose you did not implement INotifyPropertyChanged in the class which contains the property you bound to, doing so should be the easiest solution to the problem.
Backgorund
I am currently writing a program that allows a user to select a manufacture from a combo box. The combo box is created in wpf using the following wpf code segment:
<ComboBox Height="23" Margin="40.422,128.423,229.908,0" Name="itemProductManufacture" ToolTip="Click to open drop down menu" VerticalAlignment="Top" Text="Select A Manufacture" SelectionChanged="itemProductManufacture_SelectionChanged" DropDownOpened="itemProductManufacture_DropDownOpened">
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding ManufactureId}" Width="0"/>
<Image Name="itemManufactureImage" Source="{Binding ManufactureImage}" Height="15" Width="70" Stretch="Uniform"/>
<TextBlock Text="{Binding ManufactureName}"/>
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
The data is provided form a database and each entry has a Image, a name and an Id (intentionally not shown)
Problem
I am trying to code the behaviour of the combo box so when it is open the image height is 50 and when it is closed it is 15 this is so the image is larger when it is first displayed and then smaller once selected so it doesn't take up too much space on the form.
I have tried editing the image propities using code but am unable to accsess it using its name or any other children of the combo box.
Thanks
Jonathan
As you are using data template you won't be able to access the directly by its name.
Try something like this -
Image image = this.itemProductManufacture.ItemTemplate.FindName("itemManufactureImage", this) as Image;
One thing I am not clear is whether you want to change image size for all the items or the selected one? If you need to access the image for a particulat item in combobox you may have to use the ItemContainerGenerator.ContainerFromItem, as explained in following posts -
WPF - ItemsControl - How do I get find my "CheckBox" item that is in the ItemTemplate?
http://www.sitechno.com/Blog/HowToUseAttachedPropertiesAsAnExtensionMechanismForACheckedListbox.aspx
look at this, To know the various ways of finding controls - How can I find WPF controls by name or type?
You can edit image properties from code using binding. Or you can use triggers in Datatemplate. When comboboxitems checked properties change, you can change height property of corresponding image
Try this:
<Image Height = "{Binding Path=IsDropDownOpen,
RelativeSource={RelativeSource FindAncestor,
AncestorType={x:Type ComboBox}},
Converter={StaticResource myBoolToHeightConverter}}" />
An example for Converter here