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.

Friday, November 21, 2008

Trips&Ticks: Do you know how you can cast Object to AnonymousType?

I experimented with LINQ in my private project and question that was showed in title took me. I had next situation:

I set list in one method:

private void SetList()
{
SomeList.ItemsSource = ( from someTable in data.SomeTable
select new
{
someTable.Id,
someTable.Name,
Priority = someTable.Priority,
} );
In other method I want retrieve Id of selected item. How can I do it? I have found interesting solution in blog of Tomas Petricek.
private Int32 GetID()
{
Object selectedItem = DefectList.SelectedItem;

if( null != selectedItem )
{
var item = Utility.Cast( selectedItem, new
{
Id = 0,
Name = String.Empty,
Priority = String.Empty,
} );

Int32 id = item.Id;
}
}
public static T Cast( object obj, T type )
{
return (T)obj;
}

PS: As for me the best way is:
  • implement class with three like property.
  • create collection with items of this class.
  • set in ItemsSource new created collection.
  • now we can easy case Object to this class.

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.

Sunday, October 12, 2008

Little deception of List.ForEach(Action action)

I use foreach statement really often. It is useful and more compact than for. (This way is fast in same case but in same case it is slowly for performance. But I want say not about that). List<T> class has ForEach(Action action) method I thought that its implementation (and behaviour) is like foreach statement (I make this conclusion, based on the name of method) but I was confused. I have looked to Net. Reflector and saw next code:

public static void ForEach(T[] array, Action action)
{
if (array == null)
{
throw new ArgumentNullException("array");
}
if (action == null)
{
throw new ArgumentNullException("action");
}
for (int i = 0; i < array.Length; i++)
{
action(array[i]);
}
}

ForEach(Action action) method behaviour likes for statement behaviour. And I can use it like for. For example I can change main collection during execution action delegate.

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..

Monday, May 12, 2008

Problem with focus scope in WPF.

WPF contains interesting static class FocusManager. This class (more precisely: its static method SetIsFocusScope) allows to set the specified DependencyObject as a focus scope (You can read more about it here).
But we have a limitation that didn't describe in MSDN (or more precisely, I not found). We can't use all controls that were inherited from ButtonBase in this focus scope, as these controls can't capture Keyboard.Focus in this focus scope. In OnLostMouseCapture method validates whether button is located in main window's focus scope. So if it isn't, control loses Keyboard.Focus (its be after Click event).
From information from my co-worker, this behaviour will be added for buttons correct works in ToolBar.
I think that a solution of MS could be more graceful for trouble of ToolBar.

Monday, May 5, 2008

Inherit properties

When I investigated WPF feature, I was interesting how use inherit property (If consider that Binding is low performance feature). I used these properties as RegisterAttached only. I have write some test samples but these didn’t work to my of the confuse. Little search in MSDN founded the root of problem. It locate in end of inherit property document, after eulogy powerful this feature.
Note:

Although property value inheritance might appear to work for nonattached dependency properties, the inheritance behavior for a nonattached property through certain element boundaries in the run-time tree is undefined. Always use RegisterAttached to register properties where you specify Inherits in the metadata.

So, this is no surprise that my samples didn’t work. You can read more here.

Wednesday, April 16, 2008

Cider vs VS2008's builder. Just for fun

I wrote little test sample with using WPF. I added a custom class (inherit from Button) in sample's namespace. I needed to add control in application.

Taking into account my previous work experience with the implement controls, I wrote like next xmlns:local="clr-namespace:WpfApplication1;assembly=WpfApplication1" ,

I confused.

Project didn't build. It saw that couldn't find my custom class in adjusted XML namespace. In this case to my great surprise Cider parsed all correct and show Button in my case (my custom class was inherit from Button) even add correct a method for event handler.

I miss when added full type describe of namespace. In this case I had to write next: xmlns:local="clr-namespace:WpfApplication1"

Note:

If namespace of application set to use XmlnsDefinition (for example: [assembly: XmlnsDefinition( "http://www.mySite.com", "WpfApplication1" )] in AssemblyInfo.cs) and accordingly we must to write xmlns:local="http://www.mySite.com" in app. This sample isn't built and Cider doesn't parse it. We should use like code in an external dll only.

Sunday, April 13, 2008

ItemsSource tips & tricks

Describe problem.

When we wish to implement the mechanism Drag&Drop of Children for our control in WPF, particularly that our control contains children in its logical tree (in other case attached and inherit properties work incorrect sometimes). Let that control template contains some other controls inherit from ItemControl. We wish add some children to this inherit from ItemControl controls. What can we do?

If we use Items that we have a disagreeable surprise - we should add items to logical tree of internal control (previous to remove from our control's logical tree - it is the problem described above). But we can create collection inherit of IEnumerable and it is bound to ItemsSource of internal controls - all will be worked nice.

Note:

If property ItemsSource isn't equal 'null' that we can work with Items in read-only mode. If ItemsSource equal 'null' that we can full use Items (It is empty after those actions). If we need dynamic change of items we can implement INotifyPropertyChanged interface. The better solution is to use ObservableCollection for this purpose.

Tuesday, April 8, 2008

Deployment SVN (Subversion) for Windows as Home Version Control System.

I need to use Version Control System in home. It is have requirement: should be free and for Windows XP. I selected the SVN (http://subversion.tigris.org/) version at 1.4.8.12137 (It’s latest in this moment).

After installation in InstalataionFolder (default: “C:\Program Files\Subversion” you can select another) you should added repository folder and start server of SVN.

You can register repository folder to use svnadmin. First off all you should create repository folder – RepositoryFolder (I used “D:\Programming\svn”)

You do start command window (cmd.exe) in InstalataionFolder\bin and do type next command: svnadmin create "RepositoryFolder" (for example in my case: svnadmin create "D:\Programming\svn").

Note: Pay attention, we use some slash of Windows (“\”).

Now you should create service for automatic start the svn server. We use “sc.exe” for this target. “sc.exe” is located in system folder (It’s “C:\Windows\Sytstem32” in my PC). Create service: sc create svn binpath= "InstalataionFolder\bin\svnserve --service -r
"RepositoryFolder
" displayname= "SVN Server" depend= Tcpip start= auto

(In my case “sc create svn binpath= "C:\Program Files\Subversion\bin\svnserve --service -r "D:\Programming\svn" displayname= "SVN Server" depend= Tcpip start= auto”).

Note: Pay attention, we use two symbols of minuses before “service” and set space after each equals sign.

After we should uncomment “password-db = passwd” section in configure file – RepositoryFolder\conf\svnserve.conf (D:\Programming\conf\svnserve.conf in my case) and configure access to svn. We uncomment “auth-access” and uncomment and change value to “none” for “anon-access” (I deny anonymous access to svn).

You should create pair login-password in section [users] of file “RepositoryFolder\conf\passwd” (D:\Programming\conf\passwd in my case)

Now, you can start “SVN Server” service (Press Win+R and type in Run window the “services.msc” and start “SVN Server” or other with name that you have set).

And the end of article, I use a TortoiseSVN (http://tortoisesvn.tigris.org/) as client.