WPF לחצן '+' בראש שורה בדטה-גריד
-
אני מנסה ליצור לחצן בראש השורה בדטה-גריד בדומה למה שיש באקסס שלחצן זה יציג ויסתיר את גליון הנתונים המשני מה שנקרא ב WPF:
RowDetailsאולם כאשר עשיתי טמפלט ראש השורה כזה:
<DataGrid.RowHeaderTemplate> <DataTemplate> <Button Content="+" Click="Button_Click"> </Button> </DataTemplate> </DataGrid.RowHeaderTemplate>
לא ידעתי איך אני מגיע דרך ארוע הלחיצה לשורה שבה צריך לפתוח את גליון המשנה.
Private Sub Button_Click(sender As System.Object, e As System.Windows.RoutedEventArgs) Dim btn As Button = DirectCast(sender, Button) Dim row As DataGridRow = ??? If btn.Content = "+" Then btn.Content = "-" Else btn.Content = "+" End If End Sub
תודה לכולם,
ושבוע טוב.פורסם במקור בפורום CODE613 ב21/12/2013 20:13 (+02:00)
-
בWPF מקובל מאוד לא לעשות כמו שהראית, ממילא זה גם מסובך לגמרי.
מה שמקובל זה בינדינג בין הכפתור לנראות של הפירוט.
זה מסובך קצת, כי הכפתור חסר מצב, אז צריך להשתמש בToggleButton.
כמו"כ מוכרחים קונוורטר מבולאני לויסיבליטי.זה נראה פי כמה מסובך ממה שאמור להיות, אבל מנסיון, זה הרבה יותר נוח ומסודר לטווח ארוך.
אם יהיה לי זמן, מחר אעלה את קוד שעושה זאת.פורסם במקור בפורום CODE613 ב22/12/2013 21:06 (+02:00)
-
בסוף מצאתי משהו כזה:
קוד ה XAML נשאר אותו דבר, ורק עוד כמה שורות שיופעלו בלחיצה על הלחצן:Private Sub Button_Click(sender As System.Object, e As System.Windows.RoutedEventArgs) Dim btn As Button = DirectCast(sender, Button) Dim DC = DirectCast(DirectCast(btn.TemplatedParent, ContentPresenter).Parent, StackPanel).DataContext Dim FileOrFolder As FileOrFolder = DirectCast(DC, FileOrFolder) Dim dr As DataGridRow = DirectCast(dataGrid1.ItemContainerGenerator.ContainerFromItem(FileOrFolder), DataGridRow) If btn.Content = "+" Then dr.DetailsVisibility = Windows.Visibility.Visible btn.Content = Chr(150) ' מקף ארוך יותר מסימן '-' מינוס Else btn.Content = "+" dr.DetailsVisibility = Windows.Visibility.Collapsed End If End Sub
אם יש משהו יותר טוב לטווח הקצר ו/או הארוך אשמח לשומע.
תודה רבה.פורסם במקור בפורום CODE613 ב22/12/2013 21:59 (+02:00)
-
עכשיו הגעתי לחלק הקשה...
אני צריך להיות מסוגל להכניס לכל דטה-רוב טמפלט אחר של DetailsTemplate, וזה לא בעיה אם הטמפלט היה איזה פקדים פשוטים, אבל מה שאני לא יודע איך להכניס לטמפלט את גליון הנתונים שיצרתי שהוא למעשה פקד מסוג UserControl שיש בו רק דטה-גריד אחד אבל הוא צריך לקבל פרמטרים בבנאי וגם הוא OF TRecord
בקיצור: בקוד דלעיל אחרי שורה 10 צריך להכניס עוד שורה כזו:dr.DetailsTemplate = GetRowDetailsTemplate(DC.ID)
אודה מאוד מאוד לכל מי שיוכל לעזור אפי' במקצת.
תודה רבה לכולם.פורסם במקור בפורום CODE613 ב25/12/2013 01:03 (+02:00)
-
לא הבנתי את הבעיה בקשר לשורה שהראית, זה אמור לעבוד.
הקטע עם התבנית והבנאי, מאוד מעורפל.אבל אם כבר אראה לך איך עושים בצורה זאמלית את העסק.
קודם הקטע עם ה+-:<DataGrid.RowHeaderTemplate > <DataTemplate> <ToggleButton x:Name="btn" IsChecked="{Binding DetailsVisibility, Converter={StaticResource VisToBool}, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type DataGridRow}}}" > <ToggleButton.Style> <Style TargetType="{x:Type ToggleButton}" > <Setter Property="Content" Value="+" /> <Style.Triggers> <Trigger Property="IsChecked" Value="True"> <Setter Property="Content" Value="-" /> </Trigger> </Style.Triggers> </Style> </ToggleButton.Style> </ToggleButton> </DataTemplate> </DataGrid.RowHeaderTemplate>
הקוד הזה עושה שימוש בקונוורטר. Converter זה משהו מאוד שימויש, במקרה של איגוד בין דברים "לא קשורים", כגון בין צבע למספר וכו'.
הוא נעשה ע"י מופע של קלאס כלשהיא שמממשת את IValueConverter.
הדרך ליצירת מופעים בxaml הוא פשוט להצהיר על קיומם, ובשביל זה גם צריך לייבא את הNamespace של הפרוייקט הנוכחי משהו כמו:<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:WpfStyle"" x:Class="MainWindow" Title="MainWindow" Height="350" Width="525"> <Window.Resources> <local:VisToBool x:Key="VisToBool"/> </Window.Resources>
בשורה 4 מבוצע ייבוא ניימספייס לפרוייקט הנוכחי.
בשורה 7 נוצר מופע של קונוורטר.הנה הקוד של הקלאס VisToBool:
Class VisToBool Implements IValueConverter Public Function Convert(value As Object, targetType As Type, parameter As Object, culture As Globalization.CultureInfo) As Object Implements IValueConverter.Convert Return CType(value, Visibility) = Visibility.Visible End Function Public Function ConvertBack(value As Object, targetType As Type, parameter As Object, culture As Globalization.CultureInfo) As Object Implements IValueConverter.ConvertBack Return If(CBool(value) = True, Visibility.Visible, Visibility.Collapsed) End Function End Class
פורסם במקור בפורום CODE613 ב25/12/2013 18:02 (+02:00)
-
כעת לעניין טמפלטים משתנים כל שורה לפי X.
בWPF יש DataTemplateSelector. שזה מחלקה שמחזירה DataTemplate לפי הטיפוס שהיא מקבלת.הדרכה קצרה:
א. יוצרים טמפלטים לכל סיטואציה במקטע הResource של החלון (הסעיף הזה הוא לא מוכרח רק זה נח וככה עושים בד"כ).<DataTemplate x:Key="NormalTemplate"> <TextBlock Text="{Binding FirstName}" /> </DataTemplate> <DataTemplate x:Key="VipTemplate"> <StackPanel> <TextBlock Text="{Binding FirstName}" /> <TextBlock Text="{Binding LastName}" /> </StackPanel> </DataTemplate>
ב. יוצרים קלאס שיורשת מDataTemplateSelector, ודורסים את מתודת SelectTemplate שם משתמשים עם הפרמטר item לבדוק מה להחזיר
Class SelectTempletByRow Inherits DataTemplateSelector Shared win As MainWindow = Application.Current.MainWindow Public Overrides Function SelectTemplate(item As Object, container As DependencyObject) As DataTemplate If CType(item, Person).LastName = "דוד ל.ט." Then Return win.FindResource("VipTemplate") Else Return win.FindResource("NormalTemplate") End If End Function End Class
כעת מוסיפים למקטע הריסורס של החלון את הלאסס שעשינו:
<local:SelectTempletByRow x:Key="Selector" />
ומגדירים את המאפיין RowDetailsTemplateSelector של הDataGrid:
RowDetailsTemplateSelector="{StaticResource Selector}"
קצת מסובך אבל זה עקרונות מתקדמים ונחוצים בWPF, שווה!
בהצלחה.פורסם במקור בפורום CODE613 ב25/12/2013 18:23 (+02:00)
-
תודה רבה זה מצויין,
יש לי שתי שאלות לגבי הלחצן שבראש השורה:
-
איך אפשר להגדיר שאם הלחצן בשורה האחרונה של הדטה-גריד שבכפתור יהיה כתוב '*' במקום '+' כיון שזו שורה שמיועדת ליצירת שורה חדשה ולא שייך לפתוח שם גליון משנה.
-
איך אפשר לעשות שהלחצן עם ה '+' ישאר תמיד למעלה וכמו שכבר שאלתי באשכול אחר, ולא ירד תמיד לאמצע.
לגבי טפלט שונה לכל שורה בשביל ה RowDetailsTemplate, זה הרבה יותר מורכב, כיון שב RowDetailsTemplate אני צריך לדחוף גליון נתונים שזה פקד שלם שמקבל בבנאי שלו פרמטר של "טבלה גנארית OF TRecord" וגם צריך להגדיר שהגליון הזה הוא משנה ולא ראשי ולפי איזה ID הוא יציג את השורות.
אבל ישתבח שמו מצאתי פתרון בשיטה כזו:
בתוך ה XAML הגדרתי שה RowDetailsTemplate יהיה רק גריד פשוט, ואז בארוע LoadingRowDetails יצרתי מופע של פקד חדש של הגליון נתונים עם כל מה שהוא צריך ואז הוספתי את הפקד לילדים של הגריד הנ''ל, למדתי את זה מכאן.פורסם במקור בפורום CODE613 ב25/12/2013 18:47 (+02:00)
-
-
תודה רבה זה מצויין,
יש לי שתי שאלות לגבי הלחצן שבראש השורה:
-
איך אפשר להגדיר שאם הלחצן בשורה האחרונה של הדטה-גריד שבכפתור יהיה כתוב '*' במקום '+' כיון שזו שורה שמיועדת ליצירת שורה חדשה ולא שייך לפתוח שם גליון משנה.
-
איך אפשר לעשות שהלחצן עם ה '+' ישאר תמיד למעלה וכמו שכבר שאלתי באשכול אחר, ולא ירד תמיד לאמצע.
לגבי טפלט שונה לכל שורה בשביל ה RowDetailsTemplate, זה הרבה יותר מורכב, כיון שב RowDetailsTemplate אני צריך לדחוף גליון נתונים שזה פקד שלם שמקבל בבנאי שלו פרמטר של "טבלה גנארית OF TRecord" וגם צריך להגדיר שהגליון הזה הוא משנה ולא ראשי ולפי איזה ID הוא יציג את השורות.
אבל ישתבח שמו מצאתי פתרון בשיטה כזו:
בתוך ה XAML הגדרתי שה RowDetailsTemplate יהיה רק גריד פשוט, ואז בארוע LoadingRowDetails יצרתי מופע של פקד חדש של הגליון נתונים עם כל מה שהוא צריך ואז הוספתי את הפקד לילדים של הגריד הנ''ל, למדתי את זה מכאן.בקשר לשאלות, עליך כמדומני לשנות את כותרת האשכול ל"איך פותרים את כל הבעיות שיש לי בWPF במהלך הימים הללו" :lol: , וברצינות: אין שום קשר בין השאלות.
בקשר ל"מורכבות העצומה" (מה שתיארת זה מקרה קלאסי של שתי תבניות לרשימה אחת) של הפירוט, אני שמח שהסתדרת :).פורסם במקור בפורום CODE613 ב25/12/2013 19:01 (+02:00)
-