locked
How to set WPF Tab Order dynamically depending on Controls while being disabled RRS feed

  • Question

  • I am having problems with tab order when a control's IsEnabled property is being set to false. If a user enters a value in a particular textbox then tabs out of that textbox then the property in a Model class that is bound to the textbox is setting the 'IsEnabled' property to false.  The problem is that the next control being tabbed into is the one that is also being set to be disabled.  This causes the tab order to be out of order.  I tried setting the "TabIndex" for each control but that didn't work.  I also tried setting the "IsTabStop" property to the same value that is setting the IsEnabled and that didn't work.  I would appreciate any help.  Thanks!

    <TextBox Name="_geographicName" Grid.Row="0" Grid.Column="5" AutoWordSelection="True"
                             Text="{Binding Path=GeoName}" CharacterCasing="Upper"
                             IsEnabled="{Binding Path=IsStreetNameHasText}"
                             IsTabStop="{Binding Path=IsStreetNameHasText}" />

    Tuesday, March 31, 2009 10:57 PM

Answers

  • I think you have forgot to apply the interface of INotifyPropertyChanged.

    If you inherit a class from DependencyObject and INotifyPropertyChanged, this class can notify the change of itself automatically to the UI that being bound to.

    I build a simple demo to show how to set WPF Tab Order dynamically depending on Controls that being disabled.

    Hope it helps.

    XAML
    <Window x:Class="_temple.Window1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Window1" Height="300" Width="300">
        <StackPanel>
            <TextBox Name="txt1"  Width="250"   
                                        AutoWordSelection="True"  CharacterCasing="Upper"
                             IsEnabled="{Binding Path=IsStreetNameHasText}"
                             IsTabStop="{Binding Path=IsStreetNameHasText}"  >
                <TextBox.Text>
                    <Binding Path="GeoName" Mode="TwoWay" UpdateSourceTrigger="LostFocus"></Binding>
                </TextBox.Text>
            </TextBox>
            <TextBox  Name="txt2"   Width="250"   
                                        AutoWordSelection="True"
                             Text="{Binding Path=GeoName}" CharacterCasing="Upper"
                             IsEnabled="{Binding Path=IsStreetNameHasText}"
                             IsTabStop="{Binding Path=IsStreetNameHasText}" />
            <TextBox  Name="txt3"   Width="250"   
                                        AutoWordSelection="True"
                             Text="{Binding Path=GeoName}" CharacterCasing="Upper"
                             IsEnabled="{Binding Path=IsStreetNameHasText}"
                             IsTabStop="{Binding Path=IsStreetNameHasText}" />
            <TextBox  Name="txt4"   Width="250"   
                                        AutoWordSelection="True"
                             Text="{Binding Path=GeoName}" CharacterCasing="Upper"
                             IsEnabled="{Binding Path=IsStreetNameHasText}"
                             IsTabStop="{Binding Path=IsStreetNameHasText}" />
        </StackPanel>
    </Window>
    


    C#
    using System;
    using System.Collections.Generic;
    using System.Windows;
    using System.ComponentModel;
    namespace _temple
    {
        public partial class Window1 : Window
        {
            public List<Movie> MoveList = new List<Movie>();
            public Window1()
            {
                InitializeComponent();
                Display();
            }
            public void Display()
            {
                MoveList = new List<Movie>();
                MoveList.Add(new Movie(""));
                MoveList.Add(new Movie("" ));
                MoveList.Add(new Movie(""));
                MoveList.Add(new Movie(""));
                txt1.DataContext = MoveList[0];
                txt2.DataContext = MoveList[1];
                txt3.DataContext = MoveList[2];
                txt4.DataContext = MoveList[3];
            }
            private void Button_Click(object sender, RoutedEventArgs e)
            {
                string str = "";
            }
        }
        public class Movie : DependencyObject, INotifyPropertyChanged
        {
            public event PropertyChangedEventHandler PropertyChanged;
            public static readonly DependencyProperty IsStreetNameHasTextProperty =
                DependencyProperty.Register("IsStreetNameHasText", typeof(bool), typeof(Movie), new UIPropertyMetadata(true));
            public bool IsStreetNameHasText
            {
                get
                {
                    return (bool)GetValue(IsStreetNameHasTextProperty);
                }
                set
                {
                    SetValue(IsStreetNameHasTextProperty, value);
                    NotifyPropertyChanged("IsStreetNameHasText");
                }
            }
            private void NotifyPropertyChanged(String info)
            {
                if (PropertyChanged != null)
                {
                    PropertyChanged(this, new PropertyChangedEventArgs(info));
                }
            } 
            private string _GeoName = "";
            public string GeoName
            {
                get
                {
                    return _GeoName;
                }
                set
                {
                    if (value != null)
                    {
                        string str = value.ToString().Trim();
                        _GeoName = str;
                    }
                    else
                    {
                        _GeoName = "";
                    }
    
    
                    if ( _GeoName != "")
                    {
                        IsStreetNameHasText = false;
                    }
                    else
                    {
                        IsStreetNameHasText = true;
                    }
                }
            }
            public Movie(string name )
            {
                GeoName = name; 
            }
        }
    }
    

    • Marked as answer by Tao Liang Wednesday, April 8, 2009 10:03 AM
    Wednesday, April 8, 2009 10:02 AM

All replies

  • I think you have forgot to apply the interface of INotifyPropertyChanged.

    If you inherit a class from DependencyObject and INotifyPropertyChanged, this class can notify the change of itself automatically to the UI that being bound to.

    I build a simple demo to show how to set WPF Tab Order dynamically depending on Controls that being disabled.

    Hope it helps.

    XAML
    <Window x:Class="_temple.Window1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Window1" Height="300" Width="300">
        <StackPanel>
            <TextBox Name="txt1"  Width="250"   
                                        AutoWordSelection="True"  CharacterCasing="Upper"
                             IsEnabled="{Binding Path=IsStreetNameHasText}"
                             IsTabStop="{Binding Path=IsStreetNameHasText}"  >
                <TextBox.Text>
                    <Binding Path="GeoName" Mode="TwoWay" UpdateSourceTrigger="LostFocus"></Binding>
                </TextBox.Text>
            </TextBox>
            <TextBox  Name="txt2"   Width="250"   
                                        AutoWordSelection="True"
                             Text="{Binding Path=GeoName}" CharacterCasing="Upper"
                             IsEnabled="{Binding Path=IsStreetNameHasText}"
                             IsTabStop="{Binding Path=IsStreetNameHasText}" />
            <TextBox  Name="txt3"   Width="250"   
                                        AutoWordSelection="True"
                             Text="{Binding Path=GeoName}" CharacterCasing="Upper"
                             IsEnabled="{Binding Path=IsStreetNameHasText}"
                             IsTabStop="{Binding Path=IsStreetNameHasText}" />
            <TextBox  Name="txt4"   Width="250"   
                                        AutoWordSelection="True"
                             Text="{Binding Path=GeoName}" CharacterCasing="Upper"
                             IsEnabled="{Binding Path=IsStreetNameHasText}"
                             IsTabStop="{Binding Path=IsStreetNameHasText}" />
        </StackPanel>
    </Window>
    


    C#
    using System;
    using System.Collections.Generic;
    using System.Windows;
    using System.ComponentModel;
    namespace _temple
    {
        public partial class Window1 : Window
        {
            public List<Movie> MoveList = new List<Movie>();
            public Window1()
            {
                InitializeComponent();
                Display();
            }
            public void Display()
            {
                MoveList = new List<Movie>();
                MoveList.Add(new Movie(""));
                MoveList.Add(new Movie("" ));
                MoveList.Add(new Movie(""));
                MoveList.Add(new Movie(""));
                txt1.DataContext = MoveList[0];
                txt2.DataContext = MoveList[1];
                txt3.DataContext = MoveList[2];
                txt4.DataContext = MoveList[3];
            }
            private void Button_Click(object sender, RoutedEventArgs e)
            {
                string str = "";
            }
        }
        public class Movie : DependencyObject, INotifyPropertyChanged
        {
            public event PropertyChangedEventHandler PropertyChanged;
            public static readonly DependencyProperty IsStreetNameHasTextProperty =
                DependencyProperty.Register("IsStreetNameHasText", typeof(bool), typeof(Movie), new UIPropertyMetadata(true));
            public bool IsStreetNameHasText
            {
                get
                {
                    return (bool)GetValue(IsStreetNameHasTextProperty);
                }
                set
                {
                    SetValue(IsStreetNameHasTextProperty, value);
                    NotifyPropertyChanged("IsStreetNameHasText");
                }
            }
            private void NotifyPropertyChanged(String info)
            {
                if (PropertyChanged != null)
                {
                    PropertyChanged(this, new PropertyChangedEventArgs(info));
                }
            } 
            private string _GeoName = "";
            public string GeoName
            {
                get
                {
                    return _GeoName;
                }
                set
                {
                    if (value != null)
                    {
                        string str = value.ToString().Trim();
                        _GeoName = str;
                    }
                    else
                    {
                        _GeoName = "";
                    }
    
    
                    if ( _GeoName != "")
                    {
                        IsStreetNameHasText = false;
                    }
                    else
                    {
                        IsStreetNameHasText = true;
                    }
                }
            }
            public Movie(string name )
            {
                GeoName = name; 
            }
        }
    }
    

    • Marked as answer by Tao Liang Wednesday, April 8, 2009 10:03 AM
    Wednesday, April 8, 2009 10:02 AM
  • Thanks for helping with this... I will give it a try.  Thanks again, I really appreciate it!
    Monday, April 13, 2009 5:10 PM