מדריך WPF – שימוש ב Data Binding: שימוש ב IValueConverter
ישנם פעמים בהם נרצה לעשות Binding בין תכונת יעד ותכונת מקור מטיפוסים שונים. לדוגמא, נרצה לעשות תוכנית שבה סימון CheckBox מעלימה כפתור ואילו הורדת הסימון מציגה אותו. לשם כך יש לבצע קישור בין התכונות Visibility של הכפתור מטיפוס Visibility לבין תכונת IsChecked של ה CheckBox מטיפוס Boolean.
בדוגמא הבאה אנו מנסים לבצע סנכרון שכזה:
<Window x:Class="ValueConverterDemo.MainWindow"
>="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
>:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow"
Height="350"
Width="525">
<StackPanel>
<Button Content="button"
Visibility="{Binding ElementName=checkbox, Path=IsChecked}" />
<CheckBox x:Name="checkbox"
Content="hide button?" />
</StackPanel>
</Window>
הרצה של דוגמא זו תדווח על שגיאה "שקטה" במהלך ביצוע ה Binding (תופיע הודעה בחלון ה Debug Output), הבעיה היא שהטיפוסים שונים ולכן לא ברור כיצד לעשות את הסנכרון.
כדי לבצע את ההמרה בין הטיפוסים יש להגדיר מחלקה חדשה המממשת את הממשק IValueConverter. מחלקה זו תאפשר לנו להוסיף לוגיקה משלנו בעת ביצוע ה Binding. הפונקציה המרכזית שיש לממשק זה נקראת Convert. פונקציה זו נקראת כאשר מתבצע Binding ממקור כלשהוא ליעד כלשהוא. פונקציה זו מקבלת מספר פרמטרים כאשר החשוב ביניהם נקרא Value מטיפוס objecy והוא הערך המקורי שיש להמיר. הערך המוחזר מהפונקציה Convert הוא הערך לאחר שעבר המרה.
במקרה שלנו נרצה להמיר את הערך המתקבל מ Boolean לערך מטיפוס Visibility. נעשה זאת ע"י הוספת מחלקה חדשה שתממש IValueConverter באופן הבא:
using System;
using System.Globalization;
using System.Windows;
using System.Windows.Data;
namespace ValueConverterDemo
{
public class NotBooleanToVisibilityConverter : IValueConverter
{
public object Convert(
object value,
Type targetType,
object parameter,
CultureInfo culture)
{
bool boolValue = (bool)value;
if (boolValue)
{
return Visibility.Collapsed;
}
else
{
return Visibility.Visible;
}
}
public object ConvertBack(
object value,
Type targetType,
object parameter,
CultureInfo culture)
{
throw new NotImplementedException();
}
}
}
הפונקציה השנייה שיש לממש בממשק IValueConverter היא הפונקציה ConvertBack שעובד באותה צורה, רק שהיא ממירה מערך היעד לערך מקור ולכן צריכה לעשות את הפעולה ההפוכה למה שהתבצע ב Convert. פונקציה זו רלוונטית רק כאשר מבצעים Binding בעל Mode מטיפוס TwoWay או OneWayToSource. בשאר המקרים ניתן לוותר על מימוש פונקציה זו.
כעת לאחר שיצרנו את המימוש שלנו ל IValueConverter נרצה להשתמש בו.
ראשית יש לבצע מיפוי של .NET namespace ל XML namespace באופן הבא:
>:local="clr-namespace:ValueConverterDemo"
וכעת ניצור מופע של המחלקה שלנו ב Resources של החלון:
<Window.Resources>
<local:NotBooleanToVisibilityConverter
x:Key="notBooleanToVisibilityConverter" />
</Window.Resources>
נותר רק להוסיף את הפרמטר Converter ל Binding שהגדרנו מקודם:
<StackPanel>
<Button Content="button"
Visibility="{Binding ElementName=checkbox,
Path=IsChecked,
Converter={StaticResource notBooleanToVisibilityConverter}}" />
<CheckBox x:Name="checkbox"
Content="hide button?" />
</StackPanel>
הקוד המלא של התוכנית מופיע להלן. מומלץ להריץ בעצמכם ולהתנסות בדוגמא:
<Window x:Class="ValueConverterDemo.MainWindow"
>="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
>:x="http://schemas.microsoft.com/winfx/2006/xaml"
>:local="clr-namespace:ValueConverterDemo"
Title="MainWindow"
Height="350"
Width="525">
<Window.Resources>
<local:NotBooleanToVisibilityConverter
x:Key="notBooleanToVisibilityConverter" />
</Window.Resources>
<StackPanel>
<Button Content="button"
Visibility="{Binding ElementName=checkbox,
Path=IsChecked,
Converter={StaticResource notBooleanToVisibilityConverter}}" />
<CheckBox x:Name="checkbox"
Content="hide button?" />
</StackPanel>
</Window>
תגובות בפייסבוק