views:

80

answers:

2

Hello,

I get no binding errors and this code works at another place. I haven`t found out yet what I do now differently to the code where it works and its not that much code.

In UserControl.Resource:

<Style TargetType="TextBox">
    <Setter Property="BorderBrush"  Value="DarkBlue"/>
    <Setter Property="BorderThickness" Value="1" />
    <Setter Property="Margin" Value="0,1,0,1" />
    <Setter Property="Validation.ErrorTemplate">
        <Setter.Value>
            <ControlTemplate>
                <StackPanel Orientation="Horizontal">
                    <AdornedElementPlaceholder />
                    <Grid Margin="2,0,0,0">
                        <Ellipse Width="20" Height="20" Fill="Red"/>
                        <TextBlock Foreground="White" Text="X" FontWeight="Bold" HorizontalAlignment="Center" VerticalAlignment="Center"/>
                    </Grid>
                </StackPanel>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
    <Style.Triggers>
        <Trigger Property="Validation.HasError" Value="True">
            <Setter Property="ToolTip" Value="{Binding RelativeSource={RelativeSource Self},Path=(Validation.Errors)[0].ErrorContent}" />
        </Trigger>
    </Style.Triggers>
</Style>

Below in Xaml too:

    <TextBlock Height="23" HorizontalAlignment="Left" Margin="22,90,0,0"  Text="Keywords" VerticalAlignment="Top" />
    <TextBox  Height="23" HorizontalAlignment="Left" Margin="22,108,0,0"  VerticalAlignment="Top" Width="244">
        <Binding Path="Tags" Mode="TwoWay" UpdateSourceTrigger="PropertyChanged">
            <Binding.ValidationRules>
                <DataErrorValidationRule ValidatesOnTargetUpdated="False"/>
            </Binding.ValidationRules>
        </Binding>
    </TextBox>

The button SAVE in my ViewModel is only activated when the Model.Tags property is longer 10 chars input from the user. The button activation/disable works fine when I enter 10,11 and then back 8 chars. All the property changes are fired.

Model:

namespace TBM.Model
{
    public class Document : EntityBase , IDataErrorInfo
    {
        public int Id { get; set; }
        public string DocumentName { get; set; }
        public string Tags { get; set; }
        public byte[] DocumentData { get; set; }
        public int PeriodId { get; set; }


        string IDataErrorInfo.Error { get { return null; } }

        string IDataErrorInfo.this[string propertyName]
        {
            get { return this.GetValidationError(propertyName); }
        }

        public bool IsValid
        {
            get
            {
                foreach (string property in ValidatedProperties)
                    if (GetValidationError(property) != null)
                        return false;

                return true;
            }
        }

        static readonly string[] ValidatedProperties =   {  "Tags", };

        private string GetValidationError(string propertyName)
        {
            if (Array.IndexOf(ValidatedProperties, propertyName) < 0)
                return null;

            string error = null;

            switch (propertyName)
            {               
                case "Tags": error = this.IsTagsEmpty(Tags); break;

                default:
                    Debug.Fail("Unexpected property being validated on Document: " + propertyName);
                    break;
            }
            return error;
        }  

        private string IsTagsEmpty(string value)
        {
            if (value != null && value.Trim().Length >= 10)
                return null;
            else
               return "The keywords must have at least 10 chars!";            
        }
    }
}

ViewModel:

 public RelayCommand SaveDocumentCommand
        {
            get { return _saveDocumentCommand ?? (_saveDocumentCommand = new RelayCommand(() => SaveDocument(),() => CanSaveDocument())); }
        }

        private bool CanSaveDocument()
        {
            return _document.IsValid;
        }

...

What does not work is the ErrorTemplate with the red Ellipse is not showing at all?

UPDATE: Exactly the below code works in a TEST project. But in my productive project It does not find the Resource??? Why the heck this?

<TextBlock Height="23" HorizontalAlignment="Left" Margin="22,89,0,0"  Text="Keywords" VerticalAlignment="Top" />
        <TextBox Style="{StaticResource bla}" Height="23" HorizontalAlignment="Left" Margin="22,109,0,0"  VerticalAlignment="Top" Width="244">
            <Binding Path="Tags" Mode="TwoWay" UpdateSourceTrigger="PropertyChanged">
                <Binding.ValidationRules>
                    <DataErrorValidationRule ValidatesOnTargetUpdated="False"  ValidationStep="UpdatedValue"  />
                </Binding.ValidationRules>
            </Binding>
        </TextBox>


<UserControl.Resources>

         <Style x:Name="bla" TargetType="TextBox">
            <Setter Property="BorderBrush"  Value="DarkBlue"/>
            <Setter Property="BorderThickness" Value="1" />
            <Setter Property="Margin" Value="0,1,0,1" />
            <Setter Property="Validation.ErrorTemplate">
                <Setter.Value>
                    <ControlTemplate>
                        <StackPanel Orientation="Horizontal">                          
                            <AdornedElementPlaceholder />
                            <Grid Margin="2,0,0,0">
                                <Ellipse Width="20" Height="20" Fill="Red"/>
                                <TextBlock Foreground="White" Text="X" FontWeight="Bold" HorizontalAlignment="Center" VerticalAlignment="Center"/>
                            </Grid>
                        </StackPanel>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
            <Style.Triggers>
                <Trigger Property="Validation.HasError" Value="True">
                    <Setter Property="ToolTip" Value="{Binding RelativeSource={RelativeSource Self},Path=(Validation.Errors)[0].ErrorContent}" />
                </Trigger>
            </Style.Triggers>
        </Style>       

    </UserControl.Resources>
A: 

I have had a similar problem to this, it turned out not to be the template but the validation was not returning what I expected.

benPearce
the validation is always returning the value I expect. Therefore the Button is enabled/disabled.
Lisa
I put your code in to a user control, and the IsEnabled property bound to IsValid and it all worked perfectly. Have you tried running snoop over the UI to ensure that you don't have something overlapping the ellipse. Could there be another TextBox style overiding? Try taking the code out of your project and in to a test app and ensure it is working there.
benPearce
yes I still wanted to test it isolated in an extra project. Although I have still space about 30 pixel on the left side its not visible... damn maybe the margin... check it later. Ooooh snoop don`t like it does often not work as expected... Afair there is no other textbox implicit style or explicit style. I let ya know laters...
Lisa
all worked perfectly? What exactly worked? When the button was disabled did you see the red error elipse?
Lisa
Hate to say it, but your Xaml looks fine as well as the IDataErrorInfo implementation. It all worked, which is why I suggested inspecting the final output with snoop, get the control in to an error state and then find the ellipse in the Visual tree
benPearce
I tried snoop and it does not find my window lol. that happened before too It always finds the mainwindow although in the combobox is set the detailwindow with the errortemplate. Snoop just sux really... I do not like this app. I will test it now in another extra project to see it working hopefully.
Lisa
ben I have not had the time to fully check it and the bounty is over. Do you know wether I can open a bounty on the same question? if not I will later open a new question same content where you answer your same solution again (when I put the question on bounty) and I mark it as solution so you get all 50 points :) sorry was so tired yesterday...
Lisa
ok ben now I have tested it in an extra project and you were right the red elipse is showing. Damn I must check now my project whats wrong... Please tell me about my above suggestion and the 50 points bounty. If you do not care at all, I do mark your suggestion here of course as solution. :)
Lisa
ok When I use a Key on the style I get an InnerException it can`t find the ressource, erhm... how this its in the User.Resourced defined. See my Updated Text in the Init post.
Lisa
A: 

The ViewModel have to implement IDataErrorInfo, not the Model. The ViewModel binds to your View as the DataContext, not the Model, so implement the interface in ViewModel and bind to corresponding properties in XAML.

Eugene Cheverda
this is disputable... Josh Smith mvvm article puts validation in model and even more keeping the model and its validation together is prefered when you export your models via services, but in my case yes I will change that probably. Although I must say your solution has nothing to do with my problem ;-) you should have made a comment of it.
Lisa