Showing posts with label WPF. Show all posts
Showing posts with label WPF. Show all posts

Wednesday, February 24, 2010

Trips&Ticks: Easy way to navigate from XAML to class's definition.

Working with XAML code in VS2008 I have just found that I can easy jump to class's or property definition. If I press CTRL and click left mouse button on certain class or property in XAML I will be immediately switched to Object Browser (if it is class or property of .NET or external dll) or to class's or property definition in my code (if it is class or property from my sources).
Eugene Dolinskyy just pay my attention that "clear" VS2008 doesn't have this possibility. This feature is presented by ReSharper.

Monday, January 25, 2010

Zoom event for FlowDocumentPageViewer (corrected)

Download source files - here

When I wrote my article Zoom and page chaged events for FlowDocumentPageViewer I make mistake, you can read about it - there. However Martin offer solution for this problem. But I don't like this solution, overriding of OnPropertyChanged isn't best solution because this method is risen in many cases so any logic there is serious performance issue.
So how can we fix it in other way? We can find object of Slider in Visual Tree of FlowDocumentPageViewer and subscribe to ValueChanged event and call OnZoomChanged(); there.
Bingo! It fixes my trouble.

Sunday, January 24, 2010

Trips&Ticks: How to implement GroupName for RadioButton in WPF DataGrid's column?

Download source files - here

It is very easy. We should use DataGridTemplateColumn for this. My acquaintance requested to me show it. I added source code where implemented this.

Some notes:
  • You should turn off AutoGenerateColumns feature. In other case control will have duplicate values.
  • I recommend to turn off CanUserAddRows. In other case user can pick undefined row.
Enjoy Yulian ;).

Tuesday, November 24, 2009

Useful code snippets for WPF developer.

Download snippets - here

I want to share very useful in my opinion code snippets for WPF developers. Most of they were created my friend - Dmitrij Zakharov. Moreover I want to add a short description to each snippets.

Note:
The Code Snippet Inserter inserts a code snippet at the cursor location, or inserts a surround-with code snippet around the currently selected code.

Don't you know how to use code snippets? You should read next article - How to: Use Code Snippets (C#). You should copy the code snippets files to Installation directory\Microsoft Visual Studio 9.0\VC#\Snippets\1033\NetFX30 in your PC for start to use.

Let me start:
  • addowner - Adds owner to the dependency property that already exists.
  • defstyle - Code snippet for overriding DefaultStyleKey.
  • propa - Code snippet for an attached property using DependencyProperty as the backing store. It is the common code snippet that is delivered with installation of VS2008
  • propdp - Code snippet for a property using DependencyProperty as the backing store. It is the common code snippet that is delivered with installation of VS2008
  • propdpec - Code snippet for a property with value caching and events support using DependencyProperty as the backing store.
  • propdpr - Code snippet for a property using DependencyPropertyKey as the backing store.
  • routedcmd - Implements routed command executor.
  • routedevent - Declares and implements routed event.
PS: Do you want to know more? - read about Default Code Snippets.

Thursday, November 19, 2009

Zoom and page changed events for FlowDocumentPageViewer

Download source files - here

My old known Bala send to me this link.
Kent Boogaart has written an article that describes approach searching and highlighting text in FlowDocumentPageViewer - Search and Highlight Text in an Arbitrary Visual Tree. Unfortunate, two serious issues present there. I copy theirs description from msdn forum:
  1. When I change the pages of the FlowDocumentPageViewer, my Rectangular highlighted area remains the same and it is not sinking with the Text.
  2. When I zoom in or zoom out of the FlowDocumentPageViewer, the text gets zoomed but the Highlight rectangle remains in the same position.
Seems.. solution should be easy - just add DoSeach() method in PageChanged and ZoomChanged event handler methods of FlowDocumentPageViewer but it doesn't have events for notice these actions. So I decided just to implement these events :). FlowDocumentPageViewer doesn't have protected and virtual methods like OnZoomChanged or OnPageChanged. It was bad. But I found four protected and virtual methods that could help me they are OnNextPageCommand(), OnPreviousPageCommand(), OnIncreaseZoomCommand() and OnDecreaseZoomCommand(). When I added call to rise my events in theirs override methods I found that this approach wasn't work. It happened because command logic works through concurrency approach. I called the rise methods through BeginInvoke for delay the calls rise methods - and problem was solved.
You can download sources with fix above.

PS: I didn't have time for full investigate sources.. but one question. Why did Kent use SearchRectangle class? In my opinion common Rect is enough.

Monday, November 16, 2009

How to implement TextBox with PlaceHolder in WPF

Download source files - here

Using PlaceHolder is very useful thing for UI in any type application. I want to show a short way how can you implement it in WPF.
You can custom TextBox and add place-holder text on MouseEnter and remove on MouseLeave events. In this case place-holder's text looks like original text.. You can experiment with Foreground property, but truth me - you will not be satisfy.
Let my suggest other way. You can use AdornerLayer for host the place-holder text. In this case you should create class that is inherit from Adorner and this class should show your place-holder text on AdornerLayer. I've create little sample that demonstrate this.

Unfortunate, AdornerLayer doesn't presented over any Popup controls. So this solution isn't worked if you put our customized TextBox control in any Popup and as item in Menu or ComboBox controls.

Tuesday, June 16, 2009

This whimsical binding. TwoWay Binding to DataContext. Binding in WPF part 3.

I often use Binding to DataContext. It is one of the main advantage of WPF. In most case I set custom class inherit of DependencyObject (for support DependencyProperty) and I have some like next code:

<StackPanel>
<TextBlock Text="{Binding Path=Id}" />
<TextBlock Text="{Binding Path=Name}" />
<TextBlock Text="{Binding Path=Surname}"/>
...
</StackPanel>


But sometime I set a simple type for example string. For this case I can implement next Binding:

<TextBlock Text="{Binding}" />

Note: Pay attention, when we bind directly to DataContext I have written a short form (only 'binding' keyword).

But when I try to implement TwoWay Binding to DataContext. I have exception - "Two-way binding requires Path or XPath.". It cannot set a value from somewhere because it doesn't know where it came from. I can easy fix it. For example property IsChecked of CheckBox has request TwoWay Binding in metadata. For this case I have written next code:

<CheckBox IsChecked="{Binding Path=DataContext, RelativeSource={RelativeSource Self}}">

It is not so graceful, but it works.

Tuesday, June 2, 2009

Trips&Ticks: Set custom presented view for enum's fields in WPF.

Download source files - here.
Download bin files - here.

How you know, Enum can have underlying type as byte, sbyte, short, ushort, int, uint, long, or ulong. Often and often we need to present a view of Enum's values in visual elements. Usually enum's name isn't smooth for human look. As I have said we can't set for example string as underlying type and apply it as presented view.. We can use converter inherit from IValueConverter but it isn't comfortably as we need to reimplement it each time when Enum's count or order will be changed. I have implemented a simple class inherits from Attribute for set human smooth presented view:

[AttributeUsage( AttributeTargets.Field )]
public class ViewEnumAttribute : Attribute
{
public ViewEnumAttribute( String view )
{
View = view;
}

public String View
{
get;
private set;
}
}


We set AttributeTargets as Field for restrict scope of our attribute. Use of attribute is very simple:

public enum MyEnum
{
[ViewEnum( "My View Value 1" )]
MyEnumValue1,
[ViewEnum( "My View Value 2" )]
MyEnumValue2,
[ViewEnum( "My View Value 3" )]
MyEnumValue3,
}


and we extract this value when it is need:

private static object GetEnumView( Type fieldType, string fieldName )
{
FieldInfo info = fieldType.GetField( fieldName );

if( null != info )
{
foreach( ViewEnumAttribute attribute in info.GetCustomAttributes( typeof( ViewEnumAttribute ), false ) )
{
return attribute.View;
}
}

return fieldName;
}


For more details of realization you can look in attached above source files.

Monday, May 18, 2009

Implementing support of own child/children in WPF control.

Download source files - here
Download bin files - here

The best way for use child/children in WPF is customize any control with property for child/children that inherit from Control (for example ContentControl or ItemsControl). Control has wide possibility of customizing through ControlTemplate. But sometime we want to have a specific behaviour of child/children (for example if we want to implement MDI container any other specific container). What should you do for implementing this behaviour? I will show major steps in sample of simple custom panel that is inherited from FrameworkElement.
  1. First of all you should add property according type that will be contain child/children. I use Children property in my sample. It is list of UIElement. I use ObservableCollection because I need to react to collection change.
  2. You should see to show child/children in your control, you should override int VisualChildrenCount and Visual GetVisualChild( int). These method and property should get value accordingly with child/children property (child/children's count and this/these element/s according to index).
  3. Your app can correct build now but still nothing shows in app when it is run. It is happened because child/children doesn't/don't know their size and position on parent. You should override Size MeasureOverride(Size) for pass size (and calculate DesiredSize in child) to child's element and Size ArrangeOverride(Size) for pass position on parent. When you run app again you can see child/children in your custom control. You should point out to sizes that are returned in these method, MeasureOverride's size says to parent DesiredSize of your custom control and ArrangeOverride says to parent square that were taken.
  4. Now you can see that your custom control is run correct, but when you try to interact with their child/children you can see that interact is fail. It is happened because child/children property isn't/aren't added to visual tree of your custom control. AddVisualChild(Visual) method helps you in this. The best way is realized this behavior in property changed method for child or collection changed method for children. Pay attention that property changed isn't called for default value for your child/children property. We have some other reason set null as default value, but I say below about it.
  5. If you test your custom control more careful you can observe that interaction isn't complete. Yeah, visual interaction you have already implemented, but logical isn't complete. How can you observe it? Easy, try to use attached and inherit properties or DataContext - they don't work. You should add child/children to logical tree of your custom control. AddLogicalChild(Object) helps. You can call this method together with AddVisualChild.
  6. Be careful, if you want to remove element from child/children you shouldn't remember that this element should be removed from visual tree and logical tree. RemoveVisualChild(Visual) and RemoveLogicalChild(Object) help you in this.
  7. Interaction works correct now, but you can see new trouble, if you add/remove child/children in run-time you can't see any visual effect until do any change of size in app. It is happen because your custom control knows nothing about this add/remove action. If you are implementing child you can add AffectsArrange and AffectsMeasure flag to metadata of child property, they mean that custom control should do arrange and measure after each property change. If you are implementing children you should call InvalidateVisual() after each collection change. Added/Removed item shows/disappears immediately now.
  8. If you want set child/children property through XAML you should explicitly set your child/children property. You can apply to your custom control attribute ContentPropertyAttribute. So you can implicitly set your child/children property.
  9. In point #4 I have promised to say why you can't set default value no null. Pay attention that Dependency property is static member of class, so refer of one default value is added to all instances of your custom class. So you should use type that inherit form ValueType as type of dependency property or reinitialize default value in constructor (You should chose second way:).
  10. My coworker have found interesting trouble with RightToLeft support. His custom control can correct support RightToLeft only after he overrides LogicalChildren property. I can't reproduce it, but want to inform about possible trouble and solution for it.
I have written detailed road map with explanations. If some details aren't clear you can download sample with source code (case with children is implemented there).
Good luck!

Tuesday, April 21, 2009

Trips&Ticks: Do you know how you can break text in any text control of WPF?

Seems it is easy - we can use a LineBreak in code or as XAML element, but what can we do if we want to present this in attribute of XAML? Little searching shows that we should use XSLT and hexadecimally encoded value to present a literal.
<TextBlock Text="Line 1&#x0A;Line 2" />

Monday, April 13, 2009

Trips&Ticks: Do you know how can you obtain access to nested types through XAML?

Download source files - here.

XAML is a declarative XML-based language created by Microsoft which is used to initialize structured values and objects. I have already written how we can obtain access to properties of instance that located in other properties here (I have described binding's potential). But what can we do if we need to access to nested type? Which syntax should me use? It is easy: "+" indicates nested type in XAML:

local:MultiLevelButton+NestedInfo.NestedName

A lot of code snippets you can see in sources.

Tuesday, March 3, 2009

OnTime desktop light client.

Download source files - here.
Download binary files - here.

My previous customer uses OnTime as bts. It is very slowly tool. I hated it! I tired to wait any respond from this app. I have created a little and more fast tool for self using. This tool ins't complete (I have stopped to work with this customer and I can't have an access to bd for continue implementation).
Next issues need a fix:
  • SQL exception isn't handled infrequent :)
  • Icons aren't useful. Useful tooltips correct this defect ;)
  • Attachment download works in some thread that GUI (It is shameful, but I haven't had time, really)
  • App works readonly.
  • Sort and Search hasn't implemented.
  • We can work with self issues only.
Advantage:
  • It is really more fast tool than official.
  • Persist state doesn't store in bd. It saves in current PC only.
Axosoft releases new version (9.0). It is more fast than previous (8.0). But it is still no enough.
If you want to implement some features or to fix bugs you need to know that for correct run sources you need to set connection string in the next files:
  1. app.config
  2. Settings.Designer.cs
  3. OTData.dbml
  4. and Settings.settings in two points.
I have changed my connect string to "your_connecting_string" for more handy replace ;).

Tuesday, February 3, 2009

Trips&Ticks: Do you know how you can extract various instances of one object out of resources in WPF?


Download source files - here


I often use a style&template that is magnificent possibility of WPF. It allows to define one style out of resources to many elements. I can easily define instance of some object in resources and extract it there where I require. But it has one limitation:
For example for following:

XAML:
<Button x:Key="ButtonPrototype" />

C#:
Resources["ButtonPrototype"];
- returns always one instance (like Singlton Pattern). But what can I make if I require more than one such object? It isn't problem as XAML is very flexible and x:Shared attribute eliminates this trouble. Following code will extract various instances:

XAML:
<Button x:Key="ButtonPrototype" x:Shared="False" />

C#
Resources["ButtonPrototype"]


PS: In my opinion last realization shares traits with Prototype Pattern.

Saturday, January 10, 2009

Bind to many method simultaneously. Binding in WPF part 2.

Download source files - here
Download binary files - here

Target:
We have some views that have as source one shared collection. They are located in any ItemsControls (ListBoxs in my case). Those views pass form different parametrized methods (we use the ObjectDataProvider and bind to a method possibility for this purposes). How can we implement one control element's property for affect on those views? We have restricts - it is needed to make in XAML code.

Problem:
How can we pass a value of control element as parameter in bind to a methods?

Solution:
First of all we should declare some (I used "two", so I will write in next time "two" instead of "some") ObjectDataProvider objects.

<ObjectDataProvider ObjectType="{x:Type local:CItems}"
MethodName="GetMax" x:Key="max" >
<ObjectDataProvider.MethodParameters>
<system:Int32>3</system:Int32>
</ObjectDataProvider.MethodParameters>
</ObjectDataProvider>

<ObjectDataProvider ObjectType="{x:Type local:CItems}"
MethodName="GetMin" x:Key="min" >
<ObjectDataProvider.MethodParameters>
<system:Int32>3</system:Int32>
</ObjectDataProvider.MethodParameters>
</ObjectDataProvider>

Bind those objects to views:

<ListBox ItemsSource="{Binding Source={StaticResource min}}" />
<ListBox ItemsSource="{Binding Source={StaticResource max}}" />

Now we need to create a binding to control element's property that has affect to both those data provider. We use MultiBinding with Mode is set OneWayToSource for this purpose. We should implement Converter of MultiBinding. Since we set Mode as OneWayToSource we need only ConvertBack method:

public Object[] ConvertBack( Object value, Type[] targetTypes, Object parameter, CultureInfo culture )
{
Int32 cnt = targetTypes.Length;
Object[] result = new Object[ cnt ];
String str = value.ToString();

if( !String.IsNullOrEmpty( str ) )
{
Int32 index = Int32.Parse( value.ToString() );

for( Int32 i = 0; i < cnt; ++i )
{
result[ i ] = index;
}
}

return result;
}

Note: We should unbox value to Int32 other case value isn't correctly passed to method of data provider.

Now we can easy implement this MultiBinding our XAML code:

<ComboBox.Text>
<MultiBinding Mode="OneWayToSource" Converter="{StaticResource artfull}">
<Binding Source="{StaticResource max}"
Path="MethodParameters[0]"
BindsDirectlyToSource="true"
UpdateSourceTrigger="PropertyChanged"
/>
<Binding Source="{StaticResource min}"
Path="MethodParameters[0]"
BindsDirectlyToSource="true"
UpdateSourceTrigger="PropertyChanged"
/>
</MultiBinding>
</ComboBox.Text>

Now when Text property of ComboBox is changed that views will be updated. Easy and nice :). If some details isn't clear - source and binary files were attached in the beginning of article.

Saturday, December 6, 2008

Trips&Ticks: Do you know how you can use GroupName property of RadioButton for ToggleButton in WPF?


We can use GroupName property for mutually exclusive RadioButton but what can we do if we want to use mutually exclusive ToggleButton? ToggleButton doesn't have like ability. Please, do look in RadioButton what can you see? Exactly, RadioButton is inherit from ToggleButton so we can set in Template property ControlTemplate of ToggleButton. So our RadioButtons will be look like ToggleButtons besides will have GroupName property.

Tuesday, November 18, 2008

Such different paths. Binding in WPF part 1.


Download source files - here

We pleasure to using Binding in WPF. But all ways of using have we known? Only direct binds to dependency property like next code?

<TextBlock Text="{Binding Path=Height, ElementName=myButton}">

This is poor. We can bind to property of value's property. How?
Easy:

<TextBlock Text="{Binding Path=Background.(SolidColorBrush.Opacity), ElementName=myButton}"/>

and

<TextBlock Text="{Binding Path=(Button.Content).(TextBlock.FontSize), ElementName=myButton}"/>

In attached sample I show how we can use this for EventTriggers.

Wednesday, October 22, 2008

Trips&Ticks: Do you know how do you need to change properties of local file when it will be loaded, using a Relative Uri?

When I had tried to use Relative URIs for local files I found next trouble - resource wasn't found in my app. Solution for this problem is next actions: we should open properties of local file and change flag named "Copy to Output Directory" from "Do not Copy" to "Copy always".
Easy and logically.

PS: Nice article about URI in WPF - Pack URIs in Windows Presentation Foundation

Wednesday, October 15, 2008

Really multiUI window in WPF project.


Download
binary file - here
Download source files - here


Introduction.

WPF presents new way to implement visual appearance of application. We can implement it in XAML and C# files both or separately. We use Application.LoadComponent( Object, Uri ) method for load XAML files where "Uri" presents way to XAML file. So we can manipulate visual appearance presented in XAML's files load different XAML's files.

Note: We can't use x:Class attribute for root node in XAML's files. In this case compiler automatic generates C# code (in *.g.cs file) and those classes will be conflicted (more precisely - some automatic generated members will be conflicted). Thus we can't use x:Code and describe to events in XAML's files (code for support those actions were implemented in *.g.cs files).

Note: Class have been generated in XAML's file (more precisely - in *.g.cs) is normal class likes class have been generated in C# code and even we can inherit a custom class from it.

My sample.
My sample presents two mode for manager and worker that to show the personal's information. We load different XAML's files against of mode. First we show dialog window that propose to choose behaviour.

Different XAML's contains different class instants for present data:
PeopleEx (People - for worker) - presents data of personnel (less for worker and more for manager).
ManagerInfoPresenter (WorkerInfoPresenter - for worker) - get a information (different for other mode).
ManagerCapacityShow (WorkerCapacityShow - for worker) - show a diagram. It is fake but it is different for other mode.

We can implement different controls with one name in other XAML's files (for example "InformCheck" or "CapacityShow"). We found those controls in XAML's files to use FindName(String) method and we can handle some events of this controls.

CheckBox informer = (CheckBox)FindName( INFORMCHECK_NAME );
informer.Checked += new RoutedEventHandler( OnInformerChecked );
informer.Unchecked += new RoutedEventHandler( OnInformerUnchecked );


We can apply to different class members to use base class (like m_CapacityShow member) or interface (like m_InfoPresenter member).

if( AppMode.Manager == appMode )
{
...
m_InfoPresenter = new ManagerInfoPresenter();
}
else
{
...
m_InfoPresenter = new WorkerInfoPresenter();
}
...
m_CapacityShow = (Image)FindName( CAPACITYSHOW_NAME );


Summary
We can really create one class window for two (or more) behaviour of application. We don't hide any controls or elements we don't load they! It is elegant way to dynamic create application.

Wednesday, July 30, 2008

My version of Snoop (+ 2 features) of WPF


I think that every WPF developer knows that is Snoop. This is helpful tool (with source code (!!) ) for visual debugging of WPF's app at runtime. It is good but I was in need of some expansions.
  1. I needed to see Template of controls in visual tree.
  2. I needed to keep a/some couple (value and property) of control in visual tree.
I implemented this issues for self purpose and want to impart this to all.

At first. My coworker Ivan and ex-coworker Eugene implemented like issue. But their solution didn't satisfy me. It had low performance. I re-implement it and in my solution convert to xaml come true after click to "Show XAML!" button only. It increase performance in comparison with previous solutions.


For second feature I used code of Beatriz Costa that allows you to drag and drop items between data bound ItemsControls (I added a little modification for my purpose only). I added new PropertyGrid. We can drag a item from main PropertyGrid to keep PropertyGrid.

In last PropertyGrid property saves relation with its owner even if it contains different owners of properties.

Here you can find the project with this features built using VS2008.

Enjoy ;)

Thursday, June 5, 2008

Correct use ItemsSource in WPF for controls inherited from ItemsControl

Use NET.ReflectorI sometimes read MSDN forums of WPF. I have founded post with interesting problem. I was interested this trouble.

We can download sample from there. Pay attention that ListView have strange behavior: pressing "s" moves the focus to the next item. I was interested this problem and little investigate it. This action relations with search functionality. If we don't need search functionality we can easy fix it, override ToString() method:

public override string ToString()
{
return string.Empty;
}

FYI:
If you need more details why does it do, you can read next:

After you type letter 's', next methods were called:
...................
- void OnTextInput( TextCompositionEventArgs e ) of ItemsControl;
- bool DoSearch(string nextChar) of TextSearch;
- int FindMatchingPrefix(ItemsControl itemsControl, string primaryTextPath, string prefix, string newChar, int startItemIndex, bool lookForFallbackMatchToo, ref bool wasNewCharUsed) of TextSearch;

- string GetPrimaryText(object item, BindingExpression primaryTextBinding, DependencyObject primaryTextBindingHome) of TextSearch
private static string GetPrimaryText(object item, BindingExpression primaryTextBinding, DependencyObject primaryTextBindingHome)
{
//item is EmployeeInfo (!!)
DependencyObject obj2 = item as DependencyObject;

if (obj2 != null) // false
{
string str = (string) obj2.GetValue(TextProperty);
if (!string.IsNullOrEmpty(str))
{
return str;
}
}
if ((primaryTextBinding != null) && (primaryTextBindingHome != null)) //false
{
primaryTextBinding.Activate(item);
return ConvertToPlainText(primaryTextBinding.Value);
}
return ConvertToPlainText(item); //It was called
}

-string ConvertToPlainText(object o) of TextSearch
private static string ConvertToPlainText(object o)
{
FrameworkElement element = o as FrameworkElement;
if (element != null) //false
{
string plainText = element.GetPlainText();
if (plainText != null)
{
return plainText;
}
}
if (o == null) // false
{
return string.Empty;
}
return o.ToString(); //return "SDKSample.EmployeeInfo"
}


- In this FindMatchingPrefix method we prepare this string as follows
........................
string str2 = GetPrimaryText(obj3, bindingExpr, itemsControl);
if ((str2 != null) && str2.StartsWith(str, true, culture)) //"SDKSample.EmployeeInfo" is started with "s" ;) (!!!!!)
{
wasNewCharUsed = true;
num = num4;
break;
}
........................
return num;


- and in the DoSearch(string nextChar) method
........................
int itemIndex = FindMatchingPrefix(this._attachedTo, primaryTextPath, this.Prefix, nextChar, startItemIndex, lookForFallbackMatchToo, ref wasNewCharUsed);

if (itemIndex != -1)
{
if (!this.IsActive || (itemIndex != startItemIndex))
{
object item = items[itemIndex];

this._attachedTo.NavigateToItem(item, itemIndex, new ItemsControl.ItemNavigateArgs(Keyboard.PrimaryDevice, ModifierKeys.None)); //wrong code is started
this.MatchedItemIndex = itemIndex;
}

........................

Nothing is perfect..