DCSIMG
July 2007 - Posts - Just code - Tamir Khason

July 2007 - Posts

[This blog was migrated. You will not be able to comment here.
The new URL of this post is http://khason.net/blog/quick-wpf-tip-alternative-text-for-images/]


In HTML we have Alt tag, that provides alternative text for images (in case, that image is not exists), but what to do in XAML? Simple, use the power of DataTemplates and DataTriggers. In following example, I have data item with following properties Logo, which is Bitmap, Name and Description, that strings. I want to display Name text, in case, I have or want to disable no logo bitmap. Following code.

    
<DataTemplate x:Key="tmpProvider">
<
Grid>
<
TextBlock TextBlock.FontWeight="Bold" Text="{Binding Path=Name}" Visibility="Collapsed" Name="AltText"/>
<
Image Stretch="UniformToFill" Source="{Binding Path=Logo}" Name="Image" TextSearch.Text="{Binding Path=Name, Mode=OneWay}"/>
<
Grid.ToolTip>
<
StackPanel>
<
TextBlock Text="{Binding Path=Name}"/>
<
TextBlock Text="{Binding Path=Description}"/>
</
StackPanel>
</
Grid.ToolTip>
</
Grid>
<
DataTemplate.Triggers>
<
DataTrigger Binding="{Binding Path=Logo}" Value="{x:Null}">
<
Setter TargetName="AltText" Property="Visibility" Value="Visible"/>
</
DataTrigger>
</
DataTemplate.Triggers>
</
DataTemplate></PRE< P>

&#xA0;

Simple, isn't it? Thank all, those where 10 seconds about another accessibility pattern in WPF

[This blog was migrated. You will not be able to comment here.
The new URL of this post is http://khason.net/blog/microsoft-expression-blend-2-august-preview-is-available/]


New refreshment of great XAML editing tool is available for download as Preview version. What's new? Silverlight (working with Silverlight 1.0 RC) and Visual Studio 2008 (Orcas) integration support, User controls authoring, XAML editor got some improvements, such as changing font sizes, word wrapping, etc. You can now target your build by using $(BuildingExpressionBlend) property. New storyboard picker replaces old Storyboard combobox and you can finally manipulate (scaling, resizing, etc) multiple objects.

We're looking forward for your feedbacks

Download Microsoft Expression Blend 2 August Preview

[This blog was migrated. You will not be able to comment here.
The new URL of this post is http://khason.net/blog/vista-battery-saver-french-version/]


Now you can get latest beta 2 of Vista Battery Saver in French. Great thanks to Vista french community (VistaRC) for this contribution.

If you want to use Vista Battery Saver in french, just download VistaBatterySaverSetup-MUI.msi from current release location and if your locale is FR, you'll get french UI for this application

image

[This blog was migrated. You will not be able to comment here.
The new URL of this post is http://khason.net/blog/microsoft-is-going-open-source/]


Oh, my godness... Microsoft implements O'Relly OSCON. This must be really fun, how far may it take...
Open Source software labs @ Microsoft, CodePlex (it's only because of Vista Power Saver, indeed), Microsoft Shared Source, Open Source ISV Forum... Sounds really fun, can we have the sources of the next Windows version? See yourself: http://www.microsoft.com/opensource/

clip_image001

[This blog was migrated. You will not be able to comment here.
The new URL of this post is http://khason.net/blog/wpf-events-and-memory-leaks/]


Today, we'll speak about RoutedEvent and possible memory leaks associated with them. If you ever use EventManager, that's really cool mechanism of external attached event handling, you'll notice about lack of ability to unsubscribe from event handlers. What to do? Is it bad design? Actually, yes. This is possible memory leak. So, what to do with it?

First of all, you can try to null handler.

    
if(em_handler == null)
em_handler =
new RoutedEventHandler(EM_HandlePreviewMouse);
EventManager.RegisterClassHandler(typeof(Button), TextBlock.PreviewMouseDownEvent, em_handler);

...
        
em_handler = null

 

 

This will not work. Actually, the reference remains, event if handler is nulled. So, what can we do? We can use attached events. As well as we are able to attach to external event, we can unattach from it

    
if(re_handler == null)
re_handler =
new RoutedEventHandler(RE_HandlePreviewMouse);
this.AddHandler(Button.PreviewMouseDownEvent, re_handler);
...
      
this.RemoveHandler(Button.PreviewMouseDownEvent, re_handler)

          

 


So, this can give us possible solution, but what to do with really large objects? Unattaching from events will net destroy references to them. Actually, even in .NET 2.0 and 1.1, when we're using -= operator, we are not disposing handlers, we only disconnect from it.

In WPF where is new cool class, named WeakEventManager and it's implementation IWeakEventListener. But how to use them in our case? For real it's rather simple. Create new object, derrived from WeakEventManager for class you want to handle events. Just like this

    
public class WeakButtonEventManager:WeakEventManager
{
protected override void StartListening(object source)
{
Button b = source as Button;
if (b != null)
{
b.PreviewMouseDown +=
new MouseButtonEventHandler(OnPreviewMouseDown);
}
}
protected override void StopListening(object source)
{
Button b = source as Button;
if (b != null)
{
b.PreviewMouseDown -=
new MouseButtonEventHandler(OnPreviewMouseDown);
}
}

void OnPreviewMouseDown(object sender, MouseButtonEventArgs e)
{
DeliverEvent(sender, e);
}

public static void AddListener(Button source, IWeakEventListener listener)
{
Manager.ProtectedAddListener(source, listener);
}

public static void RemoveListener(Button source, IWeakEventListener listener)
{
Manager.ProtectedRemoveListener(source, listener);
}

static WeakButtonEventManager Manager
{
get
{
Type t = typeof(WeakButtonEventManager);
WeakButtonEventManager m = WeakEventManager.GetCurrentManager(t) as WeakButtonEventManager;
if (m == null)
{
m =
new WeakButtonEventManager();
WeakEventManager.SetCurrentManager(t, m);
}
return m;
}
}
}</PRE< P>

 

Then, create it's weak event implementation

    
public class ExpensiveButton : DispatcherObject, IWeakEventListener
{
Button b;
public event MouseButtonEventHandler PreviewMouseDown;

public ExpensiveButton(Button source, bool isReallyExpensive)
{
b = source;
if(isReallyExpensive)
WeakButtonEventManager.AddListener(b, this);
else
b.PreviewMouseDown += new MouseButtonEventHandler(OnPreviewMouseDown);
}

~ExpensiveButton()
{
this.Dispatcher.BeginInvoke(DispatcherPriority.Normal, (SendOrPostCallback)delegate
{
//Clean up all resources

WeakButtonEventManager.RemoveListener(b, this);
b.PreviewMouseDown -=
new MouseButtonEventHandler(OnPreviewMouseDown);
},
null);
}

void OnPreviewMouseDown(object sender, MouseButtonEventArgs e)
{
if (PreviewMouseDown != null)
PreviewMouseDown(sender, e);
}
#region IWeakEventListener Members

public bool ReceiveWeakEvent(Type managerType, object sender, EventArgs e)
{
if(managerType == typeof(WeakButtonEventManager))
{
OnPreviewMouseDown(sender, e
as MouseButtonEventArgs);
return true;
}
return false;
}

#endregion
}</PRE< P>

 

Now, you can easily handle and unhandle this class event, by disposing the event itself, rather then leave it in stack.

    
ex_button = new ExpensiveButton(butt, true);
ex_button.PreviewMouseDown +=
new MouseButtonEventHandler(EX_HandleMouseDown);

....
        
ex_button.PreviewMouseDown -= new MouseButtonEventHandler(EX_HandleMouseDown)

 


 

Happy programming

Source code for this article

[This blog was migrated. You will not be able to comment here.
The new URL of this post is http://khason.net/blog/vista-battery-saver-beta-2-is-available-for-download/]


New version of Vista Battery Saver (beta 2) is available for download from CodePlex. Except bug fixes, there is a new feature - automatic power plan change, depends on power source you are working with. I'm really wondering,&#xA0; why this feature is not available in Windows Vista out-of-the-box? For example, if you are working on battery, you'd want to use Power Saver plan, however, if you are working on AC, you'd rather use Balanced or High Performance. So, Vista Battery Saver does it for you now. All you have to do is to run it and configure plan you want to use on battery and on AC.

bbb1

In this version, I completely rewrite power aware routines, and now it's using only direct system API call, this way, I get rid over expensive timers. So, download it, use it and notice report all bugs discovered on CodePlex issues tracker and in comments.

Thank you. Remember, It still do not run itself after the installation. You should look into Start->Accessories menu to find and run it.

Download Vista Battery Saver Public Beta 2

[This blog was migrated. You will not be able to comment here.
The new URL of this post is http://khason.net/blog/hack-read-only-properties-and-fields-using-reflection/]


Today I got really confusing question: "Is it possible to change readonly property?". The first question, I asked is: "Why to do it?". The next thought was: "This is dammed interesting, whether is possible". Let's see...

One thing is sure - we can not do it regular way, but we can do it for sure by using reflection. Let's create the class itself

class TestReadOnly  { 
      
public readonly int ReadOnlyField = 10;
readonly int m_readOnlyProperty = 20;
public int ReadOnlyProperty { get { return m_readOnlyProperty; } } }

&#xA0;


Now, let's see what values we have

TestReadOnly tro1 = new TestReadOnly(); 
      
Console.WriteLine("Field value: {0}, Property value: {1}",tro1.ReadOnlyField, tro1.ReadOnlyProperty);

&#xA0;



  

Well, the results are as expected: 10 and 20. The next step is to change them from external class. Is it possible? Yes, it is. The magic word is "reflection". We'll read the read only field by using reflection

Type t = typeof(TestReadOnly); 
      
FieldInfo fi = t.GetField("ReadOnlyField");

&#xA0;


Now, we'll just set its value.

fi.SetValue(tro1, 50);


  
&#xA0;

Well, well, well. It works. Just works. You can change field value by using reflection, even if the field is read only (actually, it is not a lot of sense to du such thing).

Now, the next step of our challenge. Change the read only property. This might be tricky, 'cos actually, there is no setter at all in IL level. Let's try

PropertyInfo pi = t.GetProperty("ReadOnlyProperty"); 
      
Object[] arg = new Object[0];
pi.SetValue(tro1, 60, args);

&#xA0;


Too bad, we caught ArgumentException. It's clear, 'cos there are actually no code we can execute this way. But, if we'll look into Reflector, we can find the private read only field and set it as we did in our previous example.

PropertyInfo pi = t.GetProperty("ReadOnlyProperty"); 
      
Object[] arg = new Object[0];
try { pi.SetValue(tro1, 60, args); }
catch (ArgumentException e) {
FieldInfo
fi1 = t.GetField("m_readOnlyProperty",
BindingFlags.Instance | BindingFlags.NonPublic);
fi1.SetValue(tro1, 60);
}

&#xA0;


Now it works. Cool, we changed read only property of managed object. And what's about unmanaged code? Let's try to do the same thing with Outlook Appointment.

To access System.__ComObject (the real object in underlying model), we can not use regular GetMember method (due to the fact, that, actually, there are no managed methods there). But, we can invoke methods (note, that property getters and setters are actually methods ued to set values). How to do it? Simple. First of all, let's create boring outlook stuff

Microsoft.Office.Interop.Outlook.Application applicationObject = new Microsoft.Office.Interop.Outlook.ApplicationClass(); 
      
Microsoft.Office.Interop.Outlook.
MAPIFolder calendarFolder = applicationObject.Session.GetDefaultFolder(Microsoft.Office.Interop.Outlook.OlDefaultFolders.olFolderCalendar);
Microsoft.Office.Interop.Outlook.
Items appointments = calendarFolder.Items;

&#xA0;


Now, let's iterate appointments to get it's underlying objects. For each appointment we'll get read only LastModificationTime property

Microsoft.Office.Interop.Outlook.AppointmentItem appointment = (Microsoft.Office.Interop.Outlook.AppointmentItem)item; 
      

Console.WriteLine("COM Field: {0}", appointment.LastModificationTime);
//appointment.LastModificationTime is read only

&#xA0;


Now, let's invoke it's setter (that, actually does not exists)

appointment.GetType().InvokeMember("LastModificationTime", 
      
BindingFlags.Default | BindingFlags.SetProperty, null,
appointment,
new object[]
{
DateTime.Now });

&#xA0;


As expected, we got an exception. But this time, it's TargetInvokationException (we invoke it, remember). What to do? Not a lot. Look and seek OLEViewer to figure where set_LastModificationTime occurs and invoke it with new params. I have neither time, nor wish to do it, but you can. See the very beginning of this post. We should figure what actually happens in order to be able to change it. With unmanaged code it's much harder, that with managed. But it's possible.

Have a nice day.

Ah, don't you forgot to release all this stuff?

finally  { 
      
Console.WriteLine("COM Field: {0}", appointment.LastModificationTime);
//time to cleanup
Marshal.ReleaseComObject(appointment); }
//Just stop it from propagating
break; }
Marshal.ReleaseComObject(item); }
Marshal.ReleaseComObject(appointments);
Marshal.ReleaseComObject(calendarFolder);
Marshal.ReleaseComObject(applicationObject);

&#xA0;


:) Good programming.

[This blog was migrated. You will not be able to comment here.
The new URL of this post is http://khason.net/blog/the-blue-monster-in-sap/]


Ask Steve Clayton about who is the Blue Monster, that makes me happy. Recently, the new one has been discovered in Orlando as well as in downtown of Seattle and today he's already in SAP offices. Here the photo of the Blue Monster in SAP offices in Ra'anana. It's everywhere.

The Blue Monster in SAP in Tel-Aviv

Map image

Technorati Tags: , , ,

[This blog was migrated. You will not be able to comment here.
The new URL of this post is http://khason.net/blog/channel-8-is-on-the-air/]


We have old good Channel 9, as well we have Channel 10 and it's rather new one. Now we have Channel 8 as well - welcome, and good luck, channel 8 (nice graphite layout)

image

[This blog was migrated. You will not be able to comment here.
The new URL of this post is http://khason.net/blog/vista-battery-saver-goes-open-source/]


Due to chronic lack of time, I decided to publish full source code of Vista Battery Saver on CodePlex. I believe, that only this way, I can assure this really useful and important software to live. All developers, what to take care together with me on this soft development are welcome to join this project.

Good luck and thank you. Vista Battery Saver @ CodePlex

[This blog was migrated. You will not be able to comment here.
The new URL of this post is http://khason.net/blog/filtering-hierarchical-data-and-another-treeview-bug/]


Well, well, well. Yet another TreeView bug discovered, while answering another WPF question. But, before it, let's answer it: "How to filter hierarchical data?"

What we have? We have treeview with XML data binded to it.
What we need? To filter it - for example filter out all odd nodes in any level.
How to do? Regular way, by using Predictate generic object.

Let's start. Light, motor, camera, Data

<root>
<
leaf id="1" name="leaf1">
<
group id="1" name="group1">
<
item name="item1" id="1">
<
subitem id="1">test 1</subitem>
<
subitem id="5">test 2</subitem>
<
subitem id="5">test 3</subitem>
<
subitem id="5">test 4</subitem>
<
subitem id="5">test 5</subitem>
</
item>
<
item name="item2" id="2">
<
subitem id="1">test 1</subitem>
<
subitem id="5">test 2</subitem>
<
subitem id="5">test 3</subitem>
<
subitem id="5">test 4</subitem>
<
subitem id="5">test 5</subitem>
</
item>

.....

Data template (hierarchical of cause)

<HierarchicalDataTemplate DataType="leaf" ItemsSource ="{Binding XPath=*}"> <TextBlock Text="{Binding XPath=@name}" /> </HierarchicalDataTemplate> <HierarchicalDataTemplate DataType="group" ItemsSource ="{Binding XPath=*}"> <TextBlock Text="{Binding XPath=@name}" Foreground="Blue" /> </HierarchicalDataTemplate> <HierarchicalDataTemplate DataType="item" ItemsSource ="{Binding XPath=*}"> <TextBlock Text="{Binding XPath=@name}" Foreground="Red"/> </HierarchicalDataTemplate>
      

 

Data provider and control to host our data

<XmlDataProvider Source="XMLFile1.xml" x:Key="mydata" XPath="*"/>

      
        
<TreeView Name="myTree" ItemsSource="{Binding Source={StaticResource mydata}, XPath=*}"/> 
            

 

Now let's add checkbox to switch filtering on and off

<CheckBox Name="predCheck" Checked="onPredChecked" Unchecked="onPredUnchecked">Filter by predicate object</CheckBox>
 

And now, take care on those routed events...

void onPredChecked(object sender, RoutedEventArgs e) { ICollectionView view = CollectionViewSource.GetDefaultView(myTree.ItemsSource); view.Filter = new Predicate<object>(FilterOdds); } void onPredUnchecked(object sender, RoutedEventArgs e) { ICollectionView view = CollectionViewSource.GetDefaultView(myTree.ItemsSource); view.Filter = null; }
      

 

How to filter (FilterOdds method)?

bool FilterOdds(object item) {
XmlElement elem = item as XmlElement;
bool res = false;
if (elem != null) {
res =
int.Parse(elem.SelectSingleNode("@id").InnerText) % 2 == 1; }
return res; }

 

Now, let's filter each node, while it's expanding.

void onExpanded(object sender, RoutedEventArgs e) {
TreeViewItem item = sender as TreeViewItem;
if (item != null) {
ICollectionView view = CollectionViewSource.GetDefaultView(item.ItemsSource);
if (view != null) {
if ((bool)predCheck.IsChecked) {
view.Filter =
new Predicate<object>(FilterOdds); }
else {
//Remove comment to stop expanding level 3 //view.Filter = null; } } }
//debug
Console.WriteLine("Item {0} on container {1}", myTree.ItemContainerGenerator.IndexFromContainer(item), ItemsControl.ItemsControlFromItemContainer(item).Name); }

 

Cool everything should work, isn't it? Yes, except the weird bug of treeview, that preventing it from expanding 3rd level node, if filter applied. Try to compile and run it. If the check box unchecked (no filtering) we can easily expand each node on every level. See yourself

image

But if we'll check the checkbox, 3rd level will be inaccessible for us (as well as all deeper levels) See...

image

If you'll try to expand it, focus will move one level up and node remains collapsed. Pretty bad, huh... Good unbugged programming...

Source code for this article 

[This blog was migrated. You will not be able to comment here.
The new URL of this post is http://khason.net/blog/family-show-20/]


Tim Sneath released new version of Family Show demo application. All those, who were in my presentations, saw this outstanding example of WPF usage for multimedia fun application creation. Now it's not only with full source, but also in CodePlex source control system.

Douglas Stockwell released new version of WPF RSS reader, named RikReader (source is not available). A lot of features were added.

[This blog was migrated. You will not be able to comment here.
The new URL of this post is http://khason.net/blog/%d7%96%d7%91%d7%9c-%d7%9e%d7%99-%d7%a9%d7%9e%d7%9c%d7%9b%d7%9c%d7%9a/]


אם כל הכבוד (ויש כבוד) ממש, אבל ממש לא יפה לזבל בתגובות. ליצירת קשר ופרסום הודעות יש דרכים אחרות!

[This blog was migrated. You will not be able to comment here.
The new URL of this post is http://khason.net/blog/worldmate-for-e60-series-is-free-now/]


The new version of one of my favorite mobile applications from great developers from Lod is completely free now. Previously this great software was only available for Nokia owners. Now, the new updated version is free for all S60 devices. Download now.

via Symbianv3.com

[This blog was migrated. You will not be able to comment here.
The new URL of this post is http://khason.net/blog/justifying-of-expanders-header-button/]


From internal discussion list:

From: MS employee
Subject: Expander arrow button placement

Hi,

I have an Expander that expands in the Down direction. How do I make the Expander button be justified to the right, rather than the left which is the default?

From: Another helpful MS employee
Subject: RE: Expander arrow button placement

There is no easy way as I know, you have to restyle the Expander to achieve it.

From: Myself
Subject: RE: Expander arrow button placement

The easiest way to achieve the right justification of Expander header is by using following “double – transformation”. Actually, you are flipping the expander and then flipping back it’s header text. You’ll have to flip it’s content as well.

This way is quick and dirty, however the best way to do it is by creating custom template for header.

<Expander RenderTransformOrigin="0.5,0.5">
      
<
Expander.Header>
<
TextBlock Margin="30,0,30,0" VerticalAlignment="Top" Text="Test">
<
TextBlock.RenderTransform>
<
TransformGroup>
<
ScaleTransform ScaleX="-1" ScaleY="1"/>
</
TransformGroup>
</
TextBlock.RenderTransform>
</
TextBlock>
</
Expander.Header>
<
Expander.RenderTransform>
<
TransformGroup>
<
ScaleTransform ScaleX="-1" ScaleY="1"/>
</
TransformGroup>
</
Expander.RenderTransform>
</
Expander>

   Have a nice day.

More Posts Next page »