DCSIMG
May 2007 - Posts - Just code - Tamir Khason

May 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/fully-binded-validation-by-using-dependency-and-attached-properties/]


Yesterday, I got a request from one of my clients to create validation rule with range, binded to source or any other data. Well, that's easy - I though. However, there are a couple of tricks, you should know, to perform it.

Let's start from the beginning. Custom validation rule have to inherit from ValidationRule class, this means, that it can not be dependency object. But how said, that it can not have dependency object member? It can. So, first of all we need a validation rule.

    public class MinMaxValidationRule:ValidationRule
    {
        private Int32RangeChecker validRange;

        public Int32RangeChecker ValidRange
        {
            get { return validRange; }
            set { validRange = value; }
        }

        public override ValidationResult Validate(object value, System.Globalization.CultureInfo cultureInfo)
        {
            int res = int.MinValue;
            bool isNumber = int.TryParse(value.ToString(), out res);
            bool isValidRange = true;
            if (validRange == null)
            {
                isValidRange = true;
            }
            else
            {
                isValidRange = (res > validRange.Minimum & res < validRange.Maximum);
            }
            string errorString = !isNumber ? "The string is in incorrect format" : !isValidRange ? "The input integer is out of range" : string.Empty;
            return new ValidationResult(isNumber && isValidRange, errorString);

        }
    }

 

Well, I have not explain what is doing, right? :) Next we'll create DependencyObject Int32RangeChecker. That's simple as well.

    public class Int32RangeChecker : DependencyObject
    {
        public int Minimum
        {
            get { return (int)GetValue(MinimumProperty); }
            set { SetValue(MinimumProperty, value); }
        }
        public static readonly DependencyProperty MinimumProperty =
            DependencyProperty.Register("Minimum", typeof(int), typeof(Int32RangeChecker), new UIPropertyMetadata(int.MinValue));
        

        public int Maximum
        {
            get { return (int)GetValue(MaximumProperty); }
            set { SetValue(MaximumProperty, value); }
        }
        public static readonly DependencyProperty MaximumProperty =
            DependencyProperty.Register("Maximum", typeof(int), typeof(Int32RangeChecker), new UIPropertyMetadata(int.MaxValue));
        
    }

 

Now, let's XAML it. I'm using converter-validator explained earlier. You really do not have to do it.

    <TextBox>
      <TextBox.Text>
        <Binding Path="[1]" UpdateSourceTrigger="PropertyChanged">
          <Binding.Converter>
            <local:MyInt32Converter xmlns:local="clr-namespace:BindedValidator" />
          </Binding.Converter>
          <Binding.ValidationRules>
            <local:MinMaxValidationRule/>
              <local:MinMaxValidationRule.ValidRange>
                <local:Int32RangeChecker
                  Minimum="{Binding Source={StaticResource dataSource}, Path=MinValue}"
                  Maximum="{Binding Source={StaticResource dataSource}, Path=MaxValue}"/>
              </local:MinMaxValidationRule.ValidRange>
            </local:MinMaxValidationRule>
          </Binding.ValidationRules>
        </Binding>
      </TextBox.Text>
    </TextBox>

 

There are a couple of tricks here. First, I'm using explicitly set UpdateSourceTrigger. This one, will force the validation on source change, rather then on focus lost. The other trick, is that if you even have data context, or you want to set control as data source for internal DP - this will not work. Why? 'cos our dependency object is not part of logical tree, so you can not use ElementName or DataContext as source for internal data binding.

So far, so good. What to do if I want to bind to control (e.g. slider) in my page? You have to put local:Int32RangeChecker DependencyObject in your resources and use it following way.

<Slider Minimum="0" Maximum="20" Value="{Binding Source={StaticResource rangeConverter}, Path=Minimum, Mode=OneWayToSource}" Name="minVal"/>
<Slider Minimum="0" Maximum="20" Value="{Binding Source={StaticResource rangeConverter}, Path=Maximum, Mode=OneWayToSource}" Name="maxVal"/>
    <TextBox>
      <TextBox.Text>
        <Binding Path="[1]" UpdateSourceTrigger="PropertyChanged">
          <Binding.Converter>
            <local:MyInt32Converter xmlns:local="clr-namespace:TreeViewItemEdit" />
          </Binding.Converter>
          <Binding.ValidationRules>
            <local:MinMaxValidationRule ValidRange="{StaticResource rangeConverter}"/>
          </Binding.ValidationRules>
        </Binding>
      </TextBox.Text>
    </TextBox>

 

Well. That's one of methods to do data binding inside validation rule. The other approach is by using Attached Properties. You can create static class with properties, can be attached to your validation range source. The XAML will looks like this

<TextBox 
      l:MinMaxValidator.Minimum="{Binding Source={StaticResource rangeConverter}, Path=Minimum}"
      l:MinMaxValidator.Maximum="{Binding Source={StaticResource rangeConverter}, Path=Maximum}">
      <TextBox.Text>
        <Binding Path="[1]" UpdateSourceTrigger="PropertyChanged">
          <Binding.Converter>
            <local:MyInt32Converter xmlns:local="clr-namespace:TreeViewItemEdit" />
          </Binding.Converter>
        </Binding>
      </TextBox.Text>
    </TextBox>

 

That's looks much better, isn't it? But how to evaluate validation, while you are in completely different class. How to know where to do it and create "on-the-fly" binding from code. Look here

    public static class MinMaxValidator
    {
        public static int GetMinimum(DependencyObject obj)
        {
            return (int)obj.GetValue(MinimumProperty);
        }

        public static void SetMinimum(DependencyObject obj, int value)
        {
            obj.SetValue(MinimumProperty, value);
        }

        public static readonly DependencyProperty MinimumProperty =
            DependencyProperty.RegisterAttached("Minimum", typeof(int), typeof(MinMaxValidator), new UIPropertyMetadata(int.MinValue,OnAttachedPropertyChanged));

        public static int GetMaximum(DependencyObject obj)
        {
            return (int)obj.GetValue(MaximumProperty);
        }

        public static void SetMaximum(DependencyObject obj, int value)
        {
            obj.SetValue(MaximumProperty, value);
        }

        public static readonly DependencyProperty MaximumProperty =
            DependencyProperty.RegisterAttached("Maximum", typeof(int), typeof(MinMaxValidator), new UIPropertyMetadata(int.MaxValue,OnAttachedPropertyChanged));


        static void OnAttachedPropertyChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
        {
            TextBox tb = obj as TextBox;
            if (tb != null)
            {
                if (!tb.IsInitialized)
                {
                    EventHandler callback = null;
                    callback = delegate
                    {
                        tb.Initialized -= callback;
                        Validate(tb);
                    };
                    tb.Initialized += callback;
                }
            }
        }

        static void Validate(TextBox tb)
        { 
            BindingExpression exp = tb.GetBindingExpression(TextBox.TextProperty);
                if (exp != null && exp.ParentBinding != null)
                {
                    MinMaxValidationRule myRule = null;
                    foreach (ValidationRule rule in exp.ParentBinding.ValidationRules)
                    {
                        if (rule != null && rule is MinMaxValidationRule)
                        {
                            myRule = rule as MinMaxValidationRule;
                        }
                    }
                    if (myRule == null)
                    {
                        myRule = new MinMaxValidationRule();
                        exp.ParentBinding.ValidationRules.Add(myRule);
                    }

                    myRule.ValidRange = new Int32RangeChecker();
                    Binding minBinding = new Binding();
                    minBinding.Source = tb;
                    minBinding.Path = new PropertyPath(MinMaxValidator.MinimumProperty);
                    
                    myRule.ValidRange.Maximum = (int)tb.GetValue(MinMaxValidator.MaximumProperty);
                    myRule.Validate(tb.Text, System.Globalization.CultureInfo.CurrentCulture);
                }
        }
    }

 

Looks scary, don't it? No fear. That's really simple. The only place to look deeper is Validate and OnPropertyChange method. What we're doing there?

First of all, we have to be sure, that the property attached to textbox. Then we should check if the textbox initialized. Actually, binding and property attachment occures before initialization, so we have to subscribe to initialized event and run our code there. What we are doing in Validate method?

The target is get updated values and assign to the validation. It can be done by databinding or by regular setter. Now, let's take a binding expression from the data source, my properties were attached to. Next, we have to tear it's parent binding and find the validatorule from validator rules collection, that we need. If this one not found, we'll just create new and assign values to its range.

That's all, folks. We can bind range (or any other properties) of our validator and be quiet about triggers, data freshments and other nasty things, we suffer before Windows Presentation Foundation.

[This blog was migrated. You will not be able to comment here.
The new URL of this post is http://khason.net/blog/three-new-betas-from-live-crew/]


Today released three new betas for Live environment.

Windows Messenger goes 8.5. UI leaked earlier this week, and there is no a lot of changes. But it has some new functions. Download >>

My lovely Windows Live Writer finally goes beta 2. A lot of changes. I'm using a number of months and it's really great application. No support for hebrew or russian in current version. Download >>

Windows Live Mail goes new beta. Free mail client, can easily replace Outlook express and Windows Mail. Download >>

Great thank to developer team - great work

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


Well, some of Doron's scripts make commenting to this post(hebrew) disabled, however today I want to write about WPF accessibility issues. Someone who writes code really know what is it? I'm pretty sure, that do not. Let's make small test case. Execute regular WinForms application and Accessibility Speech engine (you can find it under Start->Accessories->Ease of Access->Narrator). Try to open calculator and go to application menu. You'll hear something like: "Menu Item Edit. Three menu items. Copy Menu Item, shorkey Control C". Where it comes from. Does narrator understand every control? How to know or control what should say? Open SpyUI from Windows SDK. Find "Calculator" node in elements tree and expand it. You'll find everything that Narrator speaking. This discovered by windows API in regular win forms.

image

Well. Now let's create simple WPF application with menu bar, button and listbox and let UISpy detect it.

image

Well, it works. But not so good. "Edit" menu item has Copy menuitem inside, but UISpy do not know about it. It's detects the containment of listbox, so it works until we have no data binded. Let's bind and see what we have.

image

Please see, that instead of what we actually see, there are System.Xml.XmlElement items are displayed. Actually, UISpy is right. We are using data, that WPF engine renders into UI. But we can not leave it this way. What to do? Make it accessible. Here the way.

First of all, we have to set TextSearch.TextPath property to our actual text. Next, override ItemContainerStyle to set its AutomationProperties.Name value to be binded to the source of text, we want to make accessible. Here the code.

    <ListBox ItemTemplate="{StaticResource template}" 
             DataContext="{StaticResource data}" ItemsSource="{Binding}"
TextSearch.TextPath="@value">
        <ListBox.ItemContainerStyle>
          <Style>
            <Setter Property="AutomationProperties.Name" Value="{Binding XPath=@value}"/>
          </Style>
        </ListBox.ItemContainerStyle>
      </ListBox>

 

If you'll bind Automation Name property inside data template it will not work, 'cos for real WPF engine do not render text objects, so the only way to do it is by overriding those properties externally. How we can tell? Right property in wrong place :)

And here the result of such approach in UISpy. Now you can run Narrator or any other accessibility application and everything will work fine.

image

The conclusions are as following:

1) UISpy is extremely important tool for accessibility check
2) WPF is not very friendly from this point of view in current version, but I'm sure, that next release will fix those issues.

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


Windows foundations are great. But how to make them work together. Today, I decided to explain how to build simple WPF application, with data, achieved from WCF OperationContracts (Methods) with simple and complicated parameters. So, let's start.

First of all, we'll create simple WPF application, then we'll add WCF Service Library to our solution. It'll create nice template with explanations what to put where. So, we'll use it AS-IS and use our WPF application as host for WCF service (this can run in different application as well). So, do everything written in the template. Create App.config and write where

<system.serviceModel>
    <services>
      <service name="FlickrHost.service1">
        <endpoint contract="FlickrHost.IService1" binding="wsHttpBinding" />
      </service>
    </services>
  </system.serviceModel>

 

Additional file with host start and stop and methods into Window1.xaml.cs

public Window1()
        {
            InitializeComponent();
            MyServiceHost.StartService();
            
        }
       

        ~Window1()
        {
            MyServiceHost.StopService();
        }

 

So far, so good. Compile, run - ERROR, AddressAccessDeniedException: "HTTP could not register URL http://+". What the hell? We can not create entrypoint as user because of UAC in Vista. So, let's see what we can do.

Open command prompt and type "netsh http show urlacl". You'll get something like this

Reserved URL            : http://+:80/wsman/
    User: NT AUTHORITY\NETWORK SERVICE
        Listen: Yes
        Delegate: Yes
        SDDL: D:(A;;GA;;;NS)

Reserved URL            : http://+:80/Temporary_Listen_Addresses/
    User: \Everyone
        Listen: Yes
        Delegate: No
        SDDL: D:(A;;GX;;;WD)

What is it? Why we can not use port 8080, provided by template. Let's add it into our account.
netsh http add urlacl url=http://+:8080/ user=DOMAIN\username. You'll get error:

Url reservation add failed, Error: 5
The requested operation requires elevation.

Run the command shell "As Administrator" and you'll success. So, UAC good or not for jews? You choose :)

Next step is creation of  ObjectDataProvider, that uses the service methods to provide results. We'll add additional method to default WCF service template, that receives no parameters. Something like this will definitely fine.

[ServiceContract()]
    public interface IService1
    {
        [OperationContract]
        string MyOperation2(string myValue);
        [OperationContract]
        string MyOperation3(DataContract1 dataContractValue);
        [OperationContract]
        string MyOperation1();
    }

    public class service1 : IService1
    {
        public string MyOperation2(string myValue)
        {
            return "Hello: " + myValue;
        }
        public string MyOperation3(DataContract1 dataContractValue)
        {
            return "Hello: " + dataContractValue.FirstName;
        }
        public string MyOperation1()
        {
            return "Hello World!";
        }
    }

 

Now, back to WPF. I believe you know, that you can bind to methods?

<ObjectDataProvider ObjectType="c:service1" x:Key="operation1" MethodName="MyOperation1"/>

 

Adding TextBlock, binded to this object and wow, we have Hello World application.

<TextBlock Text="{Binding Source={StaticResource operation1}}"/>

 

So far so good. Now, we have two additional methods, that need parameters. One is regular string, but other is DataContract from WFC service. How to do it? How to understand how to pass parameters into methods. For WPF - this is really simple. For us - not so straight forward - there is no intellisense support in XAML schema for such features in VS2005 with .NET 3.0 toolkit. What we have to do, is to use ObjectDataProvider.MethodParameters variable to set parameters for the method, bided into ObjectDataProvider. Let's rock'n'roll.

<ObjectDataProvider ObjectType="c:service1" x:Key="operation2" MethodName="MyOperation2">
      <ObjectDataProvider.MethodParameters>
        <s:String>aaa</s:String>
      </ObjectDataProvider.MethodParameters>
    </ObjectDataProvider>

 

Well. We have System mscorlib clr namespace, but what to do with object (Data Contact), defined in WCF service? For real? The same stuff. The only difference is other namespace and internal object initialization and assignment. Here comes the king.

<ObjectDataProvider ObjectType="c:service1" x:Key="operation3" MethodName="MyOperation3">
      <ObjectDataProvider.MethodParameters>
        <c:DataContract1>
          <c:DataContract1.FirstName>
            <s:String>bbb</s:String>
          </c:DataContract1.FirstName>
        </c:DataContract1>
      </ObjectDataProvider.MethodParameters>
    </ObjectDataProvider>

 

So far, we have three methods, binded to objects, achieved from WCF service provider, run by WCF data host. But wait. The data is not read only. We can change it. What's the hell, we can not notify to the object data provider about changes, there are no INotifyUpdate interface implemented as well as nothing can call us back about the change. What to do?

The simpler answer - DIY. The complicated make your client application notify about. So, I'll add TextBox and Button. Once the button clicked, I'll read information from the textbox, update my WCF service and notify about the changes.

void onClick(object sender, RoutedEventArgs e)
        {
            ObjectDataProvider odp2 = Resources["operation2"] as ObjectDataProvider;
            odp2.MethodParameters[0] = name.Text;
            odp2.Refresh();

            ObjectDataProvider odp3 = Resources["operation3"] as ObjectDataProvider;
            ((FlickrHost.DataContract1)odp3.MethodParameters[0]).FirstName = name.Text;
            odp3.Refresh();
        }

 

Well. We did it. Now let's write real world application. Read the attached source name and you'll may understand, that I'm going to write service, that reads, parses and uses beautiful images, found here. But, not today :)

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/2d-controls-in-3d-world-how-to-create-a-wheel-of-fortune-with-wpf/]


Before reading this post you should know what is geometry and trigonometry. As well as you should know, that in WPF you can "brush" 3D meshes with images or, even other XAML vector controls, inherit and create custom controls, use animations, dependency and attached properties and handle special events. Here the result. Now - how to do it

image

First of all, we have to create custom control to handle each wheel of slot. It must consists of cylinder or "tire", that will handle our images (or vectors). Additional "feature" is flexibility of the roll size, so we'll inherit Viewbox - the best choice for control, that do not really knows, how big it will be, but has something of certain size inside it.

Next we'll create our mesh - don't even enter with hand to this stuff - use any of well-knows editors or ready made meshes. Blender (this is not Expression Blend) - is good freeware choice with option to export rather good XAML geometry.

After this step we'll have to draw slots itself. Use Expression Design for it. You'll draw XAML - then you can port it into images if you'd like to.

Fine. We have 3d mesh and vector XAML slots to draw over the mesh. How to do it? Simple. Here nice example of usage my resource loader.

We'll need such control (3d mesh with images over) a lot, so it makes sense to create method for its creation. Also we'll have it static and it not going to change across the application life cycle, so preload, save and use - do it.

internal static FrameworkElement getSlotXAML(int index)
        {
            switch (index)
            {
                case 3: return loadResource<Canvas>("Resources/bar1.xaml"); break;
                case 4: return loadResource<Canvas>("Resources/bar2.xaml"); break;
                case 5: return loadResource<Canvas>("Resources/bar3.xaml"); break;
                case 2: return loadResource<Canvas>("Resources/bell.xaml"); break;
                case 1: return loadResource<Canvas>("Resources/limon.xaml"); break;
                case 6: return loadResource<Canvas>("Resources/seven.xaml"); break;
                case 0: return loadResource<Canvas>("Resources/sherry.xaml"); break;
            }
            return null;
        }

 

Then add it to panel, that wraps cylinder.

StackPanel p = new StackPanel();
            
            p.Orientation = Orientation.Horizontal;

            for (int i = 0; i < _cnvs.Length; i++)
            {
                FrameworkElement fe = getSlotXAML(i);
                fe.Width = 48;
                fe.Height = 48;
                RotateTransform rt = new RotateTransform(-90);
                rt.CenterX = fe.Width / 2;
                rt.CenterY = fe.Height / 2;
                fe.RenderTransform = rt;

                p.Children.Add(fe/*_cnvs[i]*/);
            }

 

Now, load the cylinder itself and brush it with this panel

GeometryModel3D model = loadResource<GeometryModel3D>("Resources/Cylinder.xaml");
((DiffuseMaterial)model.Material).Brush = new VisualBrush(p);

 

Now, put in into viewport and turn the lights and the camera on. The show begins. 

ModelVisual3D visual = new ModelVisual3D();
            visual.Content = model;

            Viewport3D port = new Viewport3D();
            port.Children.Add(visual);
            PerspectiveCamera camera = new PerspectiveCamera(new Point3D(0, 0, 1.7), new Vector3D(0, 0, -1), new Vector3D(0, 1, 0), 45);
            port.Camera = camera;

            ModelVisual3D lights = new ModelVisual3D();
            lights.Content = new AmbientLight(Colors.White);
            port.Children.Add(lights);

 

Fine. We have static wheel with XAML vectors over it. Let's create a movie. Very important to accelerate and decelerate the spinning speed in order to make a feel of "fear play", so we'll recreate our animation with factor of it each couple of seconds. Turn timer and do following on tick.

if (i == 10)
                i = 1;
            else
                i++;
            _animation = new DoubleAnimation(0, 360, new Duration(TimeSpan.FromSeconds(2/i)));
            _animation.RepeatBehavior = RepeatBehavior.Forever;
            ((RotateTransform3D)((GeometryModel3D)((ModelVisual3D)((Viewport3D)_element).Children[0]).Content).Transform).Rotation.BeginAnimation(AxisAngleRotation3D.AngleProperty, _animation);
            

 

What's the hell of this casting? For real? My laziness - do it better. All we have to do it apply rotation transform on our "wheel" - that's all. Now, upon the animation stop increase or decrease its speed ratio. Remember - don't too fast - cops with radars are around there and not too slow - user will fall in sleep.

if (!_ftime && _speed > 2000)
            {

                _speed = 2000;
                _goesDown = -1;
                _coef = 200;
                _ftime = true;
                _stopRequested = true;

                
            }
            if (_speed > 1000)
            {
                _coef = 500;
                _ftime = false;
            }
            else if (_speed > 500 & _speed <= 1000)
                _coef = 300;
            else if (_speed > 300 & _speed <= 500)
                _coef = 100;
            else if (_speed > 100 & _speed <= 300)
                _coef = 50;
            else if (_speed < 100)
                _coef = 5;

            if (_speed >= 2000)
            {
                _goesDown = -1;
                _speed = 2000;
            }

            if (_speed <= 2000)
            {
                _speed += _goesDown * _coef;
            }

            if (_speed <= 0)
            {
                _speed += _coef;
                _goesDown = 1;
            }

            
            
            _animation.Duration = new Duration(TimeSpan.FromMilliseconds(_speed));
            _animation.From = 0;

            ((RotateTransform3D)((GeometryModel3D)((ModelVisual3D)((Viewport3D)_element).Children[0]).Content).Transform).Rotation.BeginAnimation(AxisAngleRotation3D.AngleProperty, _animation);

 

Now, we'll have to stop it over random position, BUT the position should show full tile, so calculate it.

if (_stopRequested)
            {
                _stopRequested = false;
                _animation.Completed -= new EventHandler(_animation_Completed);
                _animation.Completed += new EventHandler(_animation_Win);
                
                _win = _rnd.Next(_cnvs.Length);
               

                _animation.To = (360  / _cnvs.Length * _win) - _animation.From;
                ((RotateTransform3D)((GeometryModel3D)((ModelVisual3D)((Viewport3D)_element).Children[0]).Content).Transform).Rotation.BeginAnimation(AxisAngleRotation3D.AngleProperty, _animation);

                return;
            }

 

To notify our future owner, you should have two read only dependency objects - one for the item (kind of enum) and the second is for item (if someone want to show it in order place). Cloning is not a big strength of WPF, so we'll have to read our tile once again.

        public static readonly DependencyPropertyKey WinningNumberPropertyKey = DependencyProperty.RegisterReadOnly("WinningNumber", typeof(int), typeof(RollSlot), new UIPropertyMetadata(0));
        
        static DependencyProperty WinningNumberProperty = WinningNumberPropertyKey.DependencyProperty;
        
        public int WinningNumber
        {
            get { return (int)GetValue(WinningNumberProperty); }
        }
        
        public static readonly DependencyPropertyKey WinningItemPropertyKey = DependencyProperty.RegisterReadOnly("WinningItem", typeof(FrameworkElement), typeof(RollSlot), new UIPropertyMetadata(null));
        
        static DependencyProperty WinningItemProperty = WinningItemPropertyKey.DependencyProperty;
        
        public FrameworkElement WinningItem
        {
            get { return (FrameworkElement)GetValue(WinningItemProperty); }
        }
        
        void _animation_Win(object sender, EventArgs e)
        {
            
            SetValue(WinningNumberPropertyKey, (int)_win);
            SetValue(WinningItemPropertyKey, GetSlotXAML((Slots)_win));
                        
        }

 

We done. The only think we should do is initialize slots and put them into our new parent.

<StackPanel Orientation="Horizontal">
      <l:RollSlot Width="300" x:Name="slot1" MouseDown="reinit"/>
      <l:RollSlot Width="300" x:Name="slot2" MouseDown="reinit"/>
      <l:RollSlot Width="300" x:Name="slot3" MouseDown="reinit"/>
    </StackPanel>

 

That's all, folks. Source code is attahced - it's dirty 'cos I'm really lazy to clean it up, so use it as is (top secret - it consist of some very useful "dead code", that wrote while testing solutions. Those can be real helpers for your job). Ah, one other thing don't forget to give me a credit and write something about me.

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/amazing-speech-recognition/]


Yochay is going to speak at Tech-Ed Orlando about speech recognition in Windows Vista. Today I saw extraordinary video about nice try to write Perl script by using this engine. It's very hilarious, really!  See yourself.

Yochay, good luck - you'll need it :)

[This blog was migrated. You will not be able to comment here.
The new URL of this post is http://khason.net/blog/create-editable-treeviewitem-using-styles/]


One of clients asked me a question: "How easily create editable TreeViewItem". I answers: "Simple. Just use styles, triggers and templates." Let's start. We need something like this.

image

First of all, let's create simple tree with data, provided by XmlDataSource.  Something like this will be good enough

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

 

Next step is to create HierarchicalDataTemplate. Just for fun, let's do it dummy way :)

<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>
  </Window.Resources>

 

Next, I want to replace TextBlock inside node with editable TextBox, but only when I have no items inside. It's possible to do it "smart way", by creating ControlTemplates of HeaderedItemControl, that looks if it has items inside and choose wherever it need to choose, But the original question was "how to do it simple way". So, we'll create data template for it

<DataTemplate x:Key="editableName">
      <TextBox Text="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=HeaderedItemsControl}, Path=(Header).InnerText}"/>
    </DataTemplate>

 

How, what we have here? In order to show current data inside the TextBox text, we have to bind it to the ancestor's header. Actually it's XmlElement in our case, to we have to get InnerText property of the node. Simple - isn't it? BTW, you can find Ancestor type of TreeViewItem - result will be exactly the same.

The last step - create a style, that has trigger for IsSelected property of TreeViewItem and change a template. Really, simple

<Style TargetType="TreeViewItem">
       <Style.Triggers>
        <Trigger Property="IsSelected" Value="True">
          <Setter Property="HeaderTemplate" Value="{StaticResource editableName}" />
        </Trigger>
      </Style.Triggers>
    </Style>

 

Now, I have a homework for you - create the same thing for those TreeViewItems, which has Items inside them. This is the clue, that might help you.

image

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/microsoft-popfly-has-been-announced/]


Today, Microsoft announced new cool tool named Popfly. What is it? Let's take The Information, make it easily accessed, and able users to build Their Own Information with Silverlight. What we got? New exciting tool of Wow.

Express Yourself

What we can do with Popfly? With Popfly everyone can build and share mash-ups, gadgets, web pages - other words Web Blocks. How to build them? Use online tutorials, professional and non-professional community. Who the target audience? Everyone, really. Everyone can build things with this simple, yet smart engine. Developers can use Addin for VS, if they do not feel good with this simple online engine :) How to make the world know? Look here

Another Wow? Probably...

Want to know more? Take a look here. After it, read dev team blog. And then, if you already do not read it, subscribe to somasegar, scottgu and johnmont - they know a lot about it :)

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


From PCWorld stuff blog:

Khason says Windows Vista Battery Saver enables and disables customizable features in Visa when your notebook's power source changes or its battery power falls under certain percent. [read more]

Yeah, Khason says... He also proves his statement with handy tests. This damned fun, that such journal write about mini-me :) 

[This blog was migrated. You will not be able to comment here.
The new URL of this post is http://khason.net/blog/staticresource-dynamicresource-xstatic-whats-all-this-about/]


So, you know to write very complicated things in XAML code, but, really, do you know what's the difference between static and dynamic resource? Do you know what's really x:Static means? We'll try today to understand differences and things we can do with this stuff. All those are markup extensions. Let's start from the very beginning - MSDN

A markup extension can be implemented to provide values for properties in attribute syntax, properties in property element syntax, or both.

StaticResource - Provides a value for a XAML property by substituting the value of an already defined resource

DynamicResource - Provides a value for a XAML property by deferring that value to be a runtime reference to a resource. A dynamic resource reference forces a new lookup each time that such a resource is accessed.

I can not tell more clear then this statement. If you want to reuse something already exists - use StaticResource, if it's changing - DynamicResource. So StaticResource is restrictive resource, when DynamicResource is not. So, other words, if you need only properties to be changed, use StaticResource, if whole object changing - use DynamicResource . The best example for this is following code

      <TextBlock Text="This is Active caption color" Background="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}"/>
      <TextBlock Text="This is not Active caption color" Background="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}">
        <TextBlock.Resources>
          <SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="Yellow" />
        </TextBlock.Resources>
      </TextBlock>
      <TextBlock Text="This is Active caption color" Background="{StaticResource {x:Static SystemColors.HighlightBrushKey}}"/>
      <TextBlock Text="This is also Active caption color" Background="{StaticResource {x:Static SystemColors.HighlightBrushKey}}">
        <TextBlock.Resources>
          <SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="Yellow" />
        </TextBlock.Resources>
      </TextBlock>

 

The result is following

image

As you can see, I completely change HighlightBrush object by using local resources. This works if the resource set as dynamic, but wont if static.

That's the reason, that you can not bind to DynamicResource, only to StaticResource properties or method results. Data binding engine can not be in peace with changing objects.

So, what is x:Static? It's XAML-defined Markup extension. There are some of them x:Type, x:Static x:Null and x:Array.

x:Static - Produces static values from value-type code entities that are not directly the type of a property's value, but can be evaluated to that type

Other words - the exit point for your static methods, properties and singletons. Why there is not x:Dynamic? Because everything else is dynamic in WPF. So, if you have singleton or static properties and method results, you want to bind to - use this extension.

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


Yesterday, I posted a beta version of Vista Battery Saver. It made a lot of wind over the statement, that Vista Aero Interface together with Windows Sidebar drain your laptop battery.

The same day at night, Nick White from development team wrote, that he has a hesitation about this statement in Windows Vista Blog. Even Jeff Atwood called me to stop voodooing... But now I have evidence, that approve my doubts. Here is comes.

Dell Latitude D820 with Windows Vista Ultimate on it works one hour more on battery without Aero and Sidebar running

If you do not believe me, here my proves.

image

Here the comparison of 20 minutes of working (regular everyday working) in my computer with and without Vista Battery Saver. It 5% difference of final charge rate. We can solve simple equation to understand, that if my battery loss 16% with Aero and 11% without in 20 minutes, it'll be completely empty within about 2 hours with and within about 3 hours without those fun features. So I was completely right, writing this simple yet useful program.

I realize, that it's possible that the part of sidebar is much more, then the part of aero, but it still makes a lot of sense to use such savers.

For those, who really interested with calculations, raw excel file is attached.

UPD 18-May-07: Following James comment, I've check the influence of hardware disabling on battery power. Results speaks for itself. Take a look.

I disabled everything I can - WiFi, DVD, wire and wireless modem, soundcard, BlueTooth, SmartCard reader and Audiocard and run the same test

dis1

Here comes the king results

image

For those, who need explanations - that exactly the same results as it was with Aero On. So, what's the conclusion? You tell me :)

Attachment updated as well with new results

[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/]


It's not a secret, that cool WDM (Aero user interface), announced in Windows Vista eat laptops' battery as hungry animal eats it's victim. But what, actually, "eat" your battery - mostly three things: Aero, Sidebar and your wide laptop screen. We have nothing to do with screen, but we can disable either Aero UI and Sidebar, while working on battery. Let me introduce Vista Battery Saver

image

This tinny program will save up to 70% of your battery by disabling those nice, but greedy Vista features. Running in task bar with private workset of 5.5M and 0% CPU it will do all work for you, by enabling and disabling customizable features when power source changed or battery power fall under certain percent.

Actually, I was inspired by similar program of Clint Rutkas and Code4Fun post (as usual, I love those guys) :). But Clint's soft was rather buggy and completely incompatible with Windows Vista Guidelines. This one is completely "Developed for Vista" - ACT 5.0 passed stuff (at least, I think so).

This is not final version, so use it for your own risk and, please, make me know about bugs or "behaviors", that make you sad :)

UPD 17-May: Home Premium installation support has been solved. All those, who had troubles to get in work in Microsoft Vista Home Premium edition, please download the new version. No other fixes in this beta release. Please make me know about other bugs

Download (beta 1) for free (MSI 901KB). You need Windows Vista Home Premium and notebook to run this program.

UPD 22-Jul: Vista Battery Saver is Open Source now. http://www.codeplex.com/vistabattery

UPD 24-Jul: New Vista Battery Saver (beta 2) has been released. More information>>

UPD 27-Jul: Vista Battery Saver (beta 2) MUI version with French user interface. More information>>

UPD 20-Aug: Vista Battery Saver (beta 2 r1)  English, German, Italian and French UI + minor fixes. More information>>

[This blog was migrated. You will not be able to comment here.
The new URL of this post is http://khason.net/blog/two-minutes-timer-windows-sidebar-gadget/]


"If it can be done in less than two minutes, do it now." - tell us wise books about personal productivity. But anyone really knows how long is 2 minutes? Most people had no idea, until now. 

Let me introduce you one of the best personal productivity tools, that help you to implement the Two Minute Rule, one of the simplest, but very powerful techniques.

2m

With this gadget in your Windows Sidebar, it's just a keystroke away. You'll plow through the backlog, close the open loops, reduce reading volume as you learn to scan for value before filing, routing, deleting or recycling. We estimate that a third of your actions take less than 2 minutes.
You'll have fun learning to focus better on how to use your time wisely and prevent getting side tracked, creating a feeling of forward motion and personal control. We've seen gains of up to an hour a day of quality discretionary time just by implementing the 2 minute rule, now made simple with the help of this convenient timer.
Open your sidebar, click on Start Timer button and start working. After two minutes you'll be notified with gentle sound and flashing message "What is your next action?"

Download Two Minutes Timer Windows Sidebar gadget.

Want to learn more about this and other personal productivity rules? Try those books:

1) Robert Crais, Two minutes rule
2) David Allen, Getting things done
3) Pamela Dodd and Doug Sundheim, The 25 Best Time Management Tools

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


Today, ex-guys from VC and .NET Connector team of SAP rises 20 megabucks in series C finding from Intel. Vivat and good luck ! :)

[This blog was migrated. You will not be able to comment here.
The new URL of this post is http://khason.net/blog/%d7%a9%d7%91%d7%99%d7%aa%d7%aa-%d7%94%d7%92%d7%9e%d7%93%d7%99%d7%9d-%d7%91%d7%90%d7%aa%d7%a8%d7%99-%d7%9e%d7%9e%d7%a9%d7%9c-%d7%96%d7%9e%d7%99%d7%9f/]


שמישהו יראה לי את המפחתים הגאונים, אשר פיתחנו את אתר השילומים של מע"מ. למה, למה לעזזל לוקח לו 12 דקות לעלות וכל דף נטען במשך 4-5 דקות לפחות. בשעה 23:00 בערך כל אתרי "ממשל זמין" כולל אתרי תשלומים והגשת דו"חות מפסיקים להיות זמינים למשך כמה שעות ל"עבודות תחזוקה". כנראה גמדים ירוקים קטנים מתחילים את משרתם בלילה ומעבירים את כל החומר שצברו במהלך היום לארכיון בכדי שלמוחורת פקידים משועממים יוכלו לטפל בו. ...או לא למוחורת... אולי זו באמת הסיבה לעבודה כזו של האתרים הללו - גמדים חמודים בשביתה?

image

More Posts Next page »