Question

I want to display the errors (IDataErrorInfo.Errors) in One place of screen instead of showing Error Content near by.. So For that I have placed textBlock in End of the Form.. How Can I Get Current Focused Element for Binding (Validation.Errors)[0].ErrorContent.

this should be done in XAML not in Code behind.

When Focus Changed then That Element's Error content is displayed in that TextBlock placed bottom of the screen..

Thanks & Regards Dineshbabu Sengottian

Was it helpful?

Solution

You can access the focused element using FocusManager.FocusedElement. Here is an example that works purely with XAML, without any code-behind (except of course for the code-behind necessary to provide IDataErrorInfo errors for testing):

<Window x:Class="ValidationTest.MainWindow"
        x:Name="w"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">

    <StackPanel>
        <TextBox x:Name="txt1" Text="{Binding Path=Value1, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True, Mode=TwoWay}"/>
        <TextBox x:Name="txt2" Text="{Binding Path=Value2, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True, Mode=TwoWay}"/>
        <TextBlock Foreground="Red" Text="{Binding 
                        RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}, 
                        Path=(FocusManager.FocusedElement).(Validation.Errors)[0].ErrorContent}"/>
    </StackPanel>
</Window>

The test class MainWindow has the following code:

namespace ValidationTest
{
    public partial class MainWindow : Window, IDataErrorInfo
    {
        public MainWindow()
        {
            InitializeComponent();

            DataContext = this;

            Value1 = "a";
            Value2 = "b";
        }

        public string Value1 { get; set; }
        public string Value2 { get; set; }

        #region IDataErrorInfo Members

        public string Error
        {
            get { return ""; }
        }

        public string this[string name]
        {
            get
            {
                if (name == "Value1" && Value1 == "x")
                {
                    return "Value 1 must not be x";
                }
                else if (name == "Value2" && Value2 == "y")
                {
                    return "Value 2 must not be y";
                }
                return "";
            }
        }

        #endregion
    }
}

For testing, you get a validation error if you put "x" in the first text box or if you put "y" in the second text box.

The error message of the currently focused text box appears below the two text boxes in the TextBlock.

Please note that this solution has one drawback. If you run the sample under the debugger, you will see those binding errors:

System.Windows.Data Error: 17 : Cannot get 'Item[]' value (type 'ValidationError') from '(Validation.Errors)' (type 'ReadOnlyObservableCollection`1'). BindingExpression:Path=(0).(1)[0].ErrorContent; DataItem='MainWindow' (Name='w'); target element is 'TextBlock' (Name=''); target property is 'Text' (type 'String') ArgumentOutOfRangeException:'System.ArgumentOutOfRangeException: Specified argument was out of the range of valid values.

These debug error messages occur when the currently focused element has not validation error, because the Validation.Errors array is empty, and therefore [0] is illegal.

You can choose either to ignore those error messages (the sample still runs fine), or you need some code-behind nevertheless, e.g. a converter that converts the IInputElement returned from FocusManager.FocusedElement to a string.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top