wpf
WPF डेटा बाइंडिंग का परिचय
खोज…
वाक्य - विन्यास
- {बाइंडिंग प्रॉपर्टीनामे} {बाइंडिंग पाथ = प्रॉपर्टीनेम} के बराबर है
- {बाइंडिंग पथ = SomeProperty.SomeOtherProperty.YetAnotherProperty}
- {बाइंडिंग पथ = SomeListProperty [1]}
पैरामीटर
पैरामीटर | विवरण |
---|---|
पथ | करने के लिए बाध्य करने के लिए पथ निर्दिष्ट करता है। यदि अनिर्दिष्ट है, तो DataContext पर ही बांधता है। |
UpdateSourceTrigger | निर्दिष्ट करता है कि बाध्यकारी स्रोत का मूल्य कब अद्यतन किया गया है। LostFocus टू LostFocus । सबसे अधिक इस्तेमाल किया जाने वाला मूल्य PropertyChanged । |
मोड | आमतौर पर OneWay या TwoWay । यदि बाध्यकारी द्वारा अनिर्दिष्ट, यह OneWay को डिफॉल्ट करता है जब तक कि बंधन लक्ष्य TwoWay होने का अनुरोध नहीं करता। एक त्रुटि तब होती है जब TwoWay का उपयोग किसी सम्मिलित रूप से प्रॉपर्टी से बाइंड करने के लिए किया जाता है, जैसे OneWay को स्पष्ट रूप से TextBox.Text प्रॉपर्टी को TextBox.Text पर TextBox.Text करते समय स्पष्ट रूप से सेट किया जाना चाहिए। |
स्रोत | वर्तमान DataContext के बजाय एक बाध्यकारी स्रोत के रूप में StaticResource का उपयोग करने की अनुमति देता है। |
RelativeSource | वर्तमान DataContext के बजाय बाध्यकारी स्रोत के रूप में एक और XAML तत्व का उपयोग करने की अनुमति देता है। |
ElementName | वर्तमान DataContext के बजाय बाध्यकारी स्रोत के रूप में नामित XAML तत्व का उपयोग करने की अनुमति देता है। |
FallbackValue | यदि बंधन विफल हो जाता है, तो यह मान बाध्यकारी लक्ष्य को प्रदान किया जाता है। |
TargetNullValue | यदि बंधन स्रोत मान null , तो यह मान बाइंडिंग लक्ष्य को प्रदान किया जाता है। |
कनवर्टर | कनवर्टर StaticResource निर्दिष्ट करता है जिसका उपयोग बंधन के मूल्य को परिवर्तित करने के लिए किया जाता है, उदाहरण के लिए एक बूलियन को Visibility एनम आइटम में परिवर्तित करें। |
ConverterParameter | कनवर्टर को प्रदान किए जाने के लिए एक वैकल्पिक पैरामीटर निर्दिष्ट करता है। यह मान स्थिर होना चाहिए और बाध्य नहीं किया जा सकता है। |
StringFormat | बाध्य मान प्रदर्शित करते समय उपयोग किए जाने वाला एक प्रारूप स्ट्रिंग निर्दिष्ट करता है। |
विलंब | (WPF 4.5+) निर्दिष्ट करने में विलंब milliseconds के लिए अद्यतन करने के लिए बाध्यकारी BindingSource में ViewModel । यह Mode=TwoWay और UpdateSourceTrigger=PropertyChanged साथ उपयोग किया जाना चाहिए। |
टिप्पणियों
UpdateSourceTrigger
डिफ़ॉल्ट रूप से, WPF बंधन स्रोत को अपडेट करता है जब नियंत्रण फोकस खो देता है। हालाँकि, यदि केवल एक ही नियंत्रण है, जो फ़ोकस प्राप्त कर सकता है - कुछ ऐसा जो उदाहरणों में सामान्य है - आपको अपडेट करने के लिए UpdateSourceTrigger=PropertyChanged
को काम करने के लिए निर्दिष्ट करना होगा।
जब तक आप प्रत्येक कीस्ट्रोक पर बाध्यकारी स्रोत को अपडेट करना महंगा नहीं होगा या डेटा सत्यापन अवांछनीय है, तब तक आप दो-तरफा बाइंडिंग पर ट्रिगर के रूप में PropertyChanged
का उपयोग करना चाहते हैं।
का उपयोग करते हुए LostFocus
एक दुर्भाग्यपूर्ण पक्ष प्रभाव पड़ता है: दबाने एक बटन चिह्नित का उपयोग कर एक फार्म जमा करने के लिए प्रवेश IsDefault
अपने बंधन का समर्थन कर संपत्ति को अद्यतन नहीं करता है, प्रभावी ढंग से अपने परिवर्तनों को नाश। सौभाग्य से, कुछ वर्कअराउंड मौजूद हैं ।
कृपया यह भी ध्यान दें कि, UWP के विपरीत, WPF (4.5+) में बाइंडिंग में Delay
संपत्ति भी है, जो कुछ TextBox
सत्यापन की तरह स्थानीय-केवल या सरल मामूली खुफिया सेटिंग्स के साथ कुछ बाइंडिंग के लिए पर्याप्त हो सकती है।
एक बूलियन को दृश्यता मान में परिवर्तित करें
यह उदाहरण लाल बॉक्स (बॉर्डर) को छुपाता है यदि चेकबॉक्स को IValueConverter
का उपयोग करके चेक नहीं किया गया है।
नोट: नीचे दिए गए उदाहरण में इस्तेमाल किया गया BooleanToVisibilityConverter
एक अंतर्निहित वैल्यू कन्वर्टर है, जो System.Windows.Controls BooleanToVisibilityConverter
में स्थित है।
XAML:
<Window x:Class="StackOverflowDataBindingExample.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<BooleanToVisibilityConverter x:Key="VisibleIfTrueConverter" />
</Window.Resources>
<StackPanel>
<CheckBox x:Name="MyCheckBox"
IsChecked="True" />
<Border Background="Red" Width="20" Height="20"
Visibility="{Binding Path=IsChecked,ElementName=MyCheckBox, Converter={StaticResource VisibleIfTrueConverter}}" />
</StackPanel>
</Window>
DataContext को परिभाषित करना
WPF में बाइंडिंग के साथ काम करने के लिए, आपको एक DataContext को परिभाषित करना होगा। DataContext बाइंडिंग को बताता है कि डिफ़ॉल्ट रूप से अपना डेटा कहां से प्राप्त करें।
<Window x:Class="StackOverflowDataBindingExample.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:StackOverflowDataBindingExample"
xmlns:vm="clr-namespace:StackOverflowDataBindingExample.ViewModels"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Window.DataContext>
<vm:HelloWorldViewModel />
</Window.DataContext>
...
</Window>
आप डेटा-कॉन्टेक्स्ट को कोड-पीछे के माध्यम से भी सेट कर सकते हैं, लेकिन यह ध्यान देने योग्य है कि XAML IntelliSense कुछ अचार है: बाइंडिंग के लिए उपलब्ध सुझाव देने के लिए IntelliSense के लिए XAML में एक दृढ़ता से टाइप किया गया DataContext सेट किया जाना चाहिए।
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataContext = new HelloWorldViewModel();
}
}
जबकि आपके डेटाकोटेक्स्ट को अधिक लचीले तरीके से परिभाषित करने में आपकी मदद करने के लिए चौखटे हैं (जैसे कि एमवीवीएम लाइट में एक व्यूमोडेल लोकेटर है जो नियंत्रण के व्युत्क्रम का उपयोग करता है ), हम इस ट्यूटोरियल के प्रयोजनों के लिए त्वरित और गंदे तरीके का उपयोग करते हैं।
आप WPF में किसी भी दृश्य तत्व के लिए एक DataContext को परिभाषित कर सकते हैं। DataContext आम तौर पर दृश्य पेड़ में पूर्वजों से विरासत में मिला है, जब तक कि यह स्पष्ट रूप से ओवरराइड नहीं किया गया है, उदाहरण के लिए एक ContentPresenter के अंदर।
INotifyPropertyChanged को कार्यान्वित करना
INotifyPropertyChanged
एक इंटरफ़ेस है जिसका उपयोग बाइंडिंग सोर्स (अर्थात DataContext) द्वारा किया जाता है ताकि यूज़र इंटरफ़ेस या अन्य घटकों को पता चल सके कि कोई प्रॉपर्टी बदली गई है। WPF स्वचालित रूप से आपके लिए UI को अपडेट कर देता है जब वह PropertyChanged
इवेंट को उठाया जाता है। इस इंटरफ़ेस को बेस क्लास पर लागू करने के लिए वांछनीय है जो आपके सभी व्यूमॉडल से विरासत में मिल सकता है।
C # 6 में, आपको इसकी आवश्यकता है:
public abstract class ViewModelBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected void NotifyPropertyChanged([CallerMemberName] string name = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}
}
यह आपको दो अलग-अलग तरीकों से NotifyPropertyChanged
को लागू करने की अनुमति देता है:
-
NotifyPropertyChanged()
, जो इसे लागू करने वाले सेटर के लिए घटना को बढ़ाएगा, विशेषता CallerMemberName के लिए धन्यवाद। -
NotifyPropertyChanged(nameof(SomeOtherProperty))
, जो SomeOtherProtyty के लिए ईवेंट को बढ़ाएगा।
.NET 4.5 और ऊपर C # 5.0 का उपयोग करने के लिए, इसके बजाय इसका उपयोग किया जा सकता है:
public abstract class ViewModelBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected void NotifyPropertyChanged([CallerMemberName] string name = null)
{
var handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(name));
}
}
}
4.5 से पहले .NET के संस्करणों में, आपको संपत्ति के नाम के लिए स्ट्रिंग स्थिरांक या अभिव्यक्ति का उपयोग करके समाधान के लिए व्यवस्थित करना होगा।
नोट: यह एक "सादे पुराने सी # वस्तु" (POCO) लागू नहीं होता है की एक संपत्ति के लिए बाध्य करने के लिए संभव है INotifyPropertyChanged
और देख सकते हैं कि बाइंडिंग बेहतर उम्मीद से काम करते हैं। यह .NET में एक छिपी हुई विशेषता है और शायद इसे टाला जाना चाहिए। विशेष रूप से क्योंकि यह मेमोरी लीक का कारण होगा जब बाइंडिंग Mode
OneTime
नहीं है ( यहां देखें)।
INotifyPropertyChanged को लागू किए बिना बाइंडिंग अद्यतन क्यों करता है?
दूसरे नामित तत्व की संपत्ति के लिए बाध्य करें
आप एक नामित तत्व पर एक संपत्ति के लिए बाध्य कर सकते हैं, लेकिन नामित तत्व दायरे में होना चाहिए।
<StackPanel>
<CheckBox x:Name="MyCheckBox" IsChecked="True" />
<TextBlock Text="{Binding IsChecked, ElementName=MyCheckBox}" />
</StackPanel>
पूर्वज की संपत्ति को बाँधो
आप RelativeSource
ट्री के पूर्वजों की संपत्ति को किसी RelativeSource
बाइंडिंग का उपयोग करके बांध सकते हैं। नज़दीकी पेड़ में उच्च नियंत्रण जो एक ही प्रकार का होता है या आपके द्वारा निर्दिष्ट प्रकार से प्राप्त होता है जिसका उपयोग बाध्यकारी स्रोत के रूप में किया जाएगा:
<Grid Background="Blue">
<Grid Background="Gray" Margin="10">
<Border Background="Red" Margin="20">
<StackPanel Background="White" Margin="20">
<Button Margin="10" Content="Button1" Background="{Binding Background, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Grid}}}" />
<Button Margin="10" Content="Button2" Background="{Binding Background, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type FrameworkElement}}}" />
</StackPanel>
</Border>
</Grid>
</Grid>
इस उदाहरण में, Button1 में एक ग्रे पृष्ठभूमि है क्योंकि निकटतम Grid
पूर्वज में एक ग्रे पृष्ठभूमि है। Button2 में एक सफेद पृष्ठभूमि है क्योंकि FrameworkElement
से प्राप्त निकटतम पूर्वज सफेद StackPanel
।
मल्टीबाइंडिंग के साथ कई मानों को बांधना
मल्टीबाइंडिंग एक ही प्रॉपर्टी में कई मानों को बाइंड करने की अनुमति देता है। निम्न उदाहरण में कई मान एक पाठ बॉक्स की पाठ संपत्ति से बंधे हैं और StringFormat संपत्ति का उपयोग करके स्वरूपित किया गया है।
<TextBlock>
<TextBlock.Text>
<MultiBinding StringFormat="{}{0} {1}">
<Binding Path="User.Forename"/>
<Binding Path="User.Surname"/>
</MultiBinding>
</TextBlock.Text>
</TextBlock>
इसके अलावा StringFormat
, एक IMultiValueConverter
भी MultiBinding के लक्ष्य के लिए एक मूल्य के लिए बाइंडिंग से मूल्यों को परिवर्तित करने के लिए इस्तेमाल किया जा सकता।
हालाँकि, MultiBindings को नेस्टेड नहीं किया जा सकता है।