WPF বৈধকরণ ত্রুটিগুলি সনাক্ত করা


115

WPF আপনি ডেটা ব্যবহার বাঁধাই সময় আপনার ডেটা লেয়ার নিক্ষিপ্ত ত্রুটি উপর ভিত্তি করে সেটআপ বৈধতা করতে ExceptionValidationRuleবা DataErrorValidationRule

ধরুন আপনার কাছে বেশ কয়েকটি নিয়ন্ত্রণ এই পদ্ধতিতে সেট আপ হয়েছে এবং আপনার একটি সংরক্ষণ বোতাম ছিল। যখন ব্যবহারকারী সংরক্ষণ বোতামটি ক্লিক করেন, আপনাকে সংরক্ষণের সাথে এগিয়ে যাওয়ার আগে কোনও বৈধতা ত্রুটি নেই তা নিশ্চিত করতে হবে। যদি বৈধতা ত্রুটিগুলি থাকে, আপনি সেগুলি ঘুরে দেখতে চান।

ডাব্লুপিএফ-এ, আপনি কীভাবে আবিষ্কার করবেন যে আপনার কোনও ডেটা বাউন্ডের নিয়ন্ত্রণের বৈধতা ত্রুটি সেট আছে?

উত্তর:


137

এই পোস্টটি অত্যন্ত সহায়ক ছিল। যারা যারা কন্ট্রিবিউট করেছে সবাইকে ধন্যবাদ। এখানে একটি লিনকুই সংস্করণ রয়েছে যা আপনি পছন্দ করবেন বা ঘৃণা করবেন।

private void CanExecute(object sender, CanExecuteRoutedEventArgs e)
{
    e.CanExecute = IsValid(sender as DependencyObject);
}

private bool IsValid(DependencyObject obj)
{
    // The dependency object is valid if it has no errors and all
    // of its children (that are dependency objects) are error-free.
    return !Validation.GetHasError(obj) &&
    LogicalTreeHelper.GetChildren(obj)
    .OfType<DependencyObject>()
    .All(IsValid);
}

1
আমি এই বিশেষ সমাধানটি অনেক পছন্দ করি!
ক্রিস্টোফিড

শুধু এই সুতার উপর হোঁচট খেয়েছে। খুব দরকারী ছোট ফাংশন। ধন্যবাদ!
ওলাভ হগেন

কেবলমাত্র সেই ডিপেন্ডেন্সিঅবজেক্টগুলিকেই নির্দিষ্ট ডেটা কনটেক্সটে আবদ্ধ করার উপায় আছে? গাছপালার ধারণাটি আমার পছন্দ নয়। নির্দিষ্ট ডেটা উত্সের সাথে লিঙ্কযুক্ত সংকলন থাকতে পারে।
জ্যাব

5
শুধু ভাবছি, আপনি কিভাবে IsValidফাংশন কল ? আমি দেখতে পাচ্ছি আপনি একটি সেট আপ করেছেন CanExecuteযা আমি অনুমান করি সেভ বোতামের কমান্ডের সাথে সম্পর্কিত। আমি কমান্ড ব্যবহার না করলে এই কাজ করবে? এবং অন্যান্য নিয়ন্ত্রণগুলির সাথে সম্পর্কিত বাটনটি কীভাবে চেক করা দরকার? এটি কীভাবে ব্যবহার করতে হবে সে সম্পর্কে আমার একমাত্র চিন্তাভাবনা IsValidযাচাই করা দরকার এমন প্রতিটি নিয়ন্ত্রণের জন্য কল করে । সম্পাদনা: দেখে মনে হচ্ছে আপনি senderসেভ বোতামটি হবেন বলে আমি প্রত্যাশা করছি valid এটা আমার কাছে ঠিক বলে মনে হচ্ছে না।
নিকোলাস মিলার

1
@ নিক মিলার একটিও Windowনির্ভরতা অবজেক্ট। আমি সম্ভবত এটির উপর কোনওরকম ইভেন্ট হ্যান্ডলারটি সেট আপ করছি Window। বিকল্পভাবে, আপনি কেবল ক্লাস IsValid(this)থেকে সরাসরি এটি কল করতে পারে Window
আকসৌমতা

47

নিম্নলিখিত কোড (ক্রিস সেল এবং ইয়ান গ্রিফিথস দ্বারা প্রোগ্রামিং ডাব্লুপিএফ বই থেকে) একটি নির্ভরতা অবজেক্ট এবং তার শিশুদের উপর সমস্ত বাধ্যতামূলক নিয়মকে বৈধতা দেয়:

public static class Validator
{

    public static bool IsValid(DependencyObject parent)
    {
        // Validate all the bindings on the parent
        bool valid = true;
        LocalValueEnumerator localValues = parent.GetLocalValueEnumerator();
        while (localValues.MoveNext())
        {
            LocalValueEntry entry = localValues.Current;
            if (BindingOperations.IsDataBound(parent, entry.Property))
            {
                Binding binding = BindingOperations.GetBinding(parent, entry.Property);
                foreach (ValidationRule rule in binding.ValidationRules)
                {
                    ValidationResult result = rule.Validate(parent.GetValue(entry.Property), null);
                    if (!result.IsValid)
                    {
                        BindingExpression expression = BindingOperations.GetBindingExpression(parent, entry.Property);
                        System.Windows.Controls.Validation.MarkInvalid(expression, new ValidationError(rule, expression, result.ErrorContent, null));
                        valid = false;
                    }
                }
            }
        }

        // Validate all the bindings on the children
        for (int i = 0; i != VisualTreeHelper.GetChildrenCount(parent); ++i)
        {
            DependencyObject child = VisualTreeHelper.GetChild(parent, i);
            if (!IsValid(child)) { valid = false; }
        }

        return valid;
    }

}

আপনি নিজের পৃষ্ঠা বা উইন্ডোতে এটির মতো ইভেন্ট হ্যান্ডলারটি আপনার বোতামে ক্লিক করতে পারেন

private void saveButton_Click(object sender, RoutedEventArgs e)
{

  if (Validator.IsValid(this)) // is valid
   {

    ....
   }
}

33

লিস্টবক্স ব্যবহার করার সময় পোস্ট করা কোডটি আমার পক্ষে কাজ করে না। আমি এটি পুনরায় লিখেছিলাম এবং এখন এটি কার্যকর হয়:

public static bool IsValid(DependencyObject parent)
{
    if (Validation.GetHasError(parent))
        return false;

    // Validate all the bindings on the children
    for (int i = 0; i != VisualTreeHelper.GetChildrenCount(parent); ++i)
    {
        DependencyObject child = VisualTreeHelper.GetChild(parent, i);
        if (!IsValid(child)) { return false; }
    }

    return true;
}

1
আমার আইটেমস নিয়ন্ত্রণে কাজ করার জন্য আপনার সমাধানটি ভোট দিন vote
জেফ টি।

1
আমার ডেটাগ্রিডে বৈধতা ত্রুটি আছে কিনা তা পরীক্ষা করতে আমি এই সমাধানটি ব্যবহার করছি। যাইহোক, এই পদ্ধতিটি আমার ভিউমডেল কমান্ড canexecute পদ্ধতিতে ডাকা হয় এবং আমি মনে করি ভিজ্যুয়াল ট্রি অবজেক্টগুলিতে অ্যাক্সেস করা কোনওভাবে এমভিভিএম প্যাটারকে লঙ্ঘন করে, তাই না? কোন বিকল্প?
ইগোর কনড্রাসভাস

16

একই সমস্যা ছিল এবং সরবরাহিত সমাধানগুলি চেষ্টা করেছিলাম। এইচ-ম্যান 2 এবং স্কিবা_ কে এর সমাধানগুলির সংমিশ্রণটি আমার ব্যতিক্রমের জন্য প্রায় সূক্ষ্মভাবে কাজ করেছিল: আমার উইন্ডোতে একটি ট্যাবকন্ট্রোল রয়েছে। এবং বৈধতার নিয়মগুলি কেবলমাত্র ট্যাবআইটেমের জন্য যা বর্তমানে দৃশ্যমান তা মূল্যায়ন করে। সুতরাং আমি লজিক্যাল ট্রিহেল্পার দ্বারা ভিজ্যুয়াল ট্রিহেল্পার প্রতিস্থাপন করেছি। এখন এটা কাজ করছে.

    public static bool IsValid(DependencyObject parent)
    {
        // Validate all the bindings on the parent
        bool valid = true;
        LocalValueEnumerator localValues = parent.GetLocalValueEnumerator();
        while (localValues.MoveNext())
        {
            LocalValueEntry entry = localValues.Current;
            if (BindingOperations.IsDataBound(parent, entry.Property))
            {
                Binding binding = BindingOperations.GetBinding(parent, entry.Property);
                if (binding.ValidationRules.Count > 0)
                {
                    BindingExpression expression = BindingOperations.GetBindingExpression(parent, entry.Property);
                    expression.UpdateSource();

                    if (expression.HasError)
                    {
                        valid = false;
                    }
                }
            }
        }

        // Validate all the bindings on the children
        System.Collections.IEnumerable children = LogicalTreeHelper.GetChildren(parent);
        foreach (object obj in children)
        {
            if (obj is DependencyObject)
            {
                DependencyObject child = (DependencyObject)obj;
                if (!IsValid(child)) { valid = false; }
            }
        }
        return valid;
    }

7

ডিনের দুর্দান্ত লিনকিউ-বাস্তবায়ন ছাড়াও, নির্ভরশীলতা সংক্রান্ত প্রকল্পগুলির জন্য একটি এক্সটেনশনে কোডটি মোড়ানোতে আমি মজা পেয়েছিলাম:

public static bool IsValid(this DependencyObject instance)
{
   // Validate recursivly
   return !Validation.GetHasError(instance) &&  LogicalTreeHelper.GetChildren(instance).OfType<DependencyObject>().All(child => child.IsValid());
}

এটি পুনঃব্যবহারযোগ্যতা বিবেচনা করে এটি অত্যন্ত সুন্দর করে তোলে।


2

আমি একটি ছোট অপ্টিমাইজেশন অফার করবে।

আপনি যদি একই নিয়ন্ত্রণগুলিতে বহুবার এটি করেন তবে আপনি নিয়ন্ত্রণের তালিকার জন্য উপরের কোডটি যুক্ত করতে পারেন যা বাস্তবে বৈধতার নিয়ম রয়েছে। তারপরে যখনই আপনাকে বৈধতার জন্য যাচাই করা দরকার তখন পুরো ভিজ্যুয়াল ট্রিের পরিবর্তে কেবলমাত্র সেই নিয়ন্ত্রণগুলিতে যান। আপনার যদি এমন অনেকগুলি নিয়ন্ত্রণ থাকে তবে এটি আরও ভাল প্রমাণিত হবে।


2

ডাব্লুপিএফ-তে ফর্ম বৈধতার জন্য এখানে একটি লাইব্রেরি রয়েছেনিউজ প্যাকেজ এখানে

নমুনা:

<Border BorderBrush="{Binding Path=(validationScope:Scope.HasErrors),
                              Converter={local:BoolToBrushConverter},
                              ElementName=Form}"
        BorderThickness="1">
    <StackPanel x:Name="Form" validationScope:Scope.ForInputTypes="{x:Static validationScope:InputTypeCollection.Default}">
        <TextBox Text="{Binding SomeProperty}" />
        <TextBox Text="{Binding SomeOtherProperty}" />
    </StackPanel>
</Border>

ধারণাটি হ'ল আমরা সংযুক্ত সম্পত্তির মাধ্যমে কোনও বৈধতা স্কোপটিকে সংজ্ঞায়িত করি যা কী ইনপুট ট্র্যাক করতে পারে তা জানিয়ে। তারপরে আমরা এটি করতে পারি:

<ItemsControl ItemsSource="{Binding Path=(validationScope:Scope.Errors),
                                    ElementName=Form}">
    <ItemsControl.ItemTemplate>
        <DataTemplate DataType="{x:Type ValidationError}">
            <TextBlock Foreground="Red"
                       Text="{Binding ErrorContent}" />
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

0

আপনি আপনার সমস্ত নিয়ন্ত্রণ গাছের উপরে পুনরাবৃত্তভাবে পুনরাবৃত্তি করতে পারেন এবং সংযুক্ত সম্পত্তি যাচাইকরণ করতে পারেন asহ্যাসেররপ্রপ্রেটি, তারপরে আপনি এটির প্রথমটিতে নজর রাখুন।

আপনি ইতিমধ্যে লিখিত অনেকগুলি সমাধানও ব্যবহার করতে পারেন আপনি উদাহরণ এবং আরও তথ্যের জন্য এই থ্রেডটি পরীক্ষা করতে পারেন


0

আপনি ডাব্লুপিএফ অ্যাপ্লিকেশন ফ্রেমওয়ার্ক (ডাব্লুএফ) এর বুকলিবারি নমুনা অ্যাপ্লিকেশনটিতে আগ্রহী হতে পারেন । এটি ডাব্লুপিএফটিতে বৈধতা কীভাবে ব্যবহার করতে হয় এবং বৈধতা ত্রুটি থাকা অবস্থায় কীভাবে সংরক্ষণ বোতামটি নিয়ন্ত্রণ করতে হয় তা দেখায়।


0

উত্তর ফর্মের মধ্যে, বৈধতা নিয়মের মাধ্যমে স্পষ্টভাবে পুনরাবৃত্তি না হয়ে আরও ভালভাবে প্রার্থনা করুন expression.UpdateSource():

if (BindingOperations.IsDataBound(parent, entry.Property))
{
    Binding binding = BindingOperations.GetBinding(parent, entry.Property);
    if (binding.ValidationRules.Count > 0)
    {
        BindingExpression expression 
            = BindingOperations.GetBindingExpression(parent, entry.Property);
        expression.UpdateSource();

        if (expression.HasError) valid = false;
    }
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.