WPF: קומבוקס שערכיו משתנים לפי בחירה בקומבובוקס אחר
-
יש לי 2 עמודות: 1. אמצעי תשלום. 2. מזהה אמצעי תשלום.
כשהכוונה היא שאתה בוחר באיזה אמצעי תשלום לשלם (לדוג' כרטיס אשראי), ואז בעמודה השניה מוצגים לך כל הכרטיסים של אותו משתמש לבחירה כדי לבחור באיזה לבצע את התשלום. וכן על זה הדרך בכל אמצעי התשלום.השאלה שלי: האם יש דרך לעשות זאת דרך הxaml או שזה חייב להתבצע דרך הקוד?
כמו כן, אם אני צריך לממש את זה בקוד, לאיזה propertis של הקומבוקס החדש אני צריך לקרוא (itemSource), ואלו ערכים להציב להם?
(לדוג' אם אני רוצה שהוא יציג רק את כרטיסי האשראי של המשתמש שהוזן בתיבת המשתמש באותה שורה, חשבתי אולי לעשות שאילתא על טבלת כרטיסי האשראי עם הID של המשתמש הזה, ולהציג את נתוני השאילתא. זה נראה לי קצת מסורבל, האם יש דרך פשוטה יותר לעשות זאת?)תודה רבה!!
פורסם במקור בפורום CODE613 ב20/07/2015 20:34 (+03:00)
-
הכי פשוט במקרה זה שימוש בConverter. מטרת הקונוורטר זה איגוד כמו בינדינג רגיל אבל למקרה בהם הערך צריך לעבור קומבינציה כל שהיא כמו המרה או התאמה, ע"י קוד, לפני שהוא עובר ליעד (וממנו בחזרה במקרה של TwoWay).
במקרה שלך אתה יכול לאגד את הItemsSource לשורה כולה (ע"י בינינג ריק בלי ציון Path), ובקונוורטר לבדוק את אמצעי התשלום ולפיהו לתשאל את המסד או הזיכרון לרשימת אמצעים תואמים.
איך עובד קונוורטר? הקונוורטר מוגדר בבינידינג ע"י הצבה בפרמטר Converter הצהרה זאמלית של מחלקה המממשת את IValueConverter (מקובל להצהיר בריסורס למקרה שימוש חוזר ולהשתמש בStaticResource בתוך ביטי הבינדינג.Text="{Binding Color, Converter={StaticResource ColorToDescription}}"
אז אתה כותב מחלקה בפרוייקט שמממשת את הממשק IValueConverter, משהו בסגנון:
public class DonToListWays : IValueConverter { public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { ... } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { throw new NotImplementedException(); } }
מוסיף בריסורס את מופע ממחלקה זו:
<local:DonToListWays x:Key="DonToListWays" />
ובבינדינג של הקומבו אתה כותב:
ItemsSource="{Binding Converter={StaticResource DonToListWays}}"
אם תשים ברייקפוינט במתודה Convert תראה שהValue תואם לסוג של השורה. ממנו תנסה להסיק בקוד רשימה מתאימה של אמצעי תשלום ולהחזיר אותם כרשימה (עם מאפיין ID כמובן לאיגוד לטבלה).
פורסם במקור בפורום CODE613 ב21/07/2015 21:47 (+03:00)
-
@דוד ל.ט.
אם תשים ברייקפוינט במתודה Convert תראה שהValue תואם לסוג של השורה. ממנו תנסה להסיק בקוד רשימה מתאימה של אמצעי תשלום ולהחזיר אותם כרשימה (עם מאפיין ID כמובן לאיגוד לטבלה).
לא הצלחתי כלל להריץ את התכנית, כתבתי כמו שאמרת והוא כותב שהמחלקה שלי לא נמצאת בניימספייס, וזה תמוה כי היא כן!!
הנה הקוד זאמל:<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:TrialSQL1" x:Class="TrialSQL1.AddTruma" Title="AddTruma" MinHeight="400" MinWidth="900" Loaded="Window_Loaded" FlowDirection="RightToLeft"> <Window.Resources> <local:MethodToListPay x:Key="MethodToListPay"/> <CollectionViewSource x:Key="donoationViewSource" Source="{Binding Donoation, Source={StaticResource avrTrumaDataSet}}"/> </Window.Resources> .... <DataGridTemplateColumn x:Name="howToPayColumn" Header="אופן התשלום" Width="SizeToHeader"> <DataGridTemplateColumn.CellTemplate> <DataTemplate> <ComboBox ItemsSource="{Binding Converter={StaticResource MethodToListPay}}"> <ComboBoxItem Content="{Binding HowToPay}"/> </ComboBox> </DataTemplate> </DataGridTemplateColumn.CellTemplate> </DataGridTemplateColumn> <DataGridTemplateColumn x:Name="idMethodPayColumn" Header="מזהה אמצעי תשלום" Width="SizeToHeader"> <DataGridTemplateColumn.CellTemplate> <DataTemplate> <ComboBox> <ComboBoxItem Content="{Binding IdMethodPay}"/> </ComboBox> </DataTemplate> </DataGridTemplateColumn.CellTemplate> </DataGridTemplateColumn> </DataGrid.Columns> </DataGrid> </Grid> </Window>
והנה הקוד של המחלקה (שעדיין לא כתבתי את הפונקציה.. אבל אפשר לראות שהיא באותו ניימספייס..)
namespace TrialSQL1 { public class MethodToListPay : IValueConverter { public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { throw new NotImplementedException(); } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { throw new NotImplementedException(); } } }
השתגע הבחור!!
פתאום הוא גם טוען שהוא לא מכיר את הדטהסט, למרות שלפני זה הכל עבד והוא הכיר אותו יפה מאד??
ולא מחקתי כלום..פורסם במקור בפורום CODE613 ב21/07/2015 23:01 (+03:00)
-
-
ניסיתי לעשות זאת על הקומבו של הסוג אמצעי...
טעות שלי!!
עכשיו אינני יודע איך במתודה שאני כותב אני בודק איזה ערך הוזן בקומבו של הסוג, כיון שאיני מצליח לקרוא לו - שהרי זה מחלקה אחרת (האם אפשר להגדיר את הקומבו כpuclic?)
כמו כן, הגדרנו שכל הדטה סט והטבלאדפטר יהיו בקובץ APP כדי שהם יהיו זמינים בכל החלונות של האפיקציה, אבל במחלקה של המתודה הם לא זמינים. האם אני צריך לאתחל מופע חדש שלהם (לכאורה כן, וא"כ מה שהגדרנו אותם בקובץ הראשי זה רק בשביל הזאמל. הלא כן?)
תודה רבה!פורסם במקור בפורום CODE613 ב22/07/2015 10:57 (+03:00)
-
האם הערך שנשלח למתודה
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
הוא הערך שהוזן לקומבו?
כמו כן, ראיתי שאני צריך ליצור מופע חדש של החלון, ואז יש לי גישה לכל המאפיינים שלו ובכלל זה הקומבוקסים שלו.פורסם במקור בפורום CODE613 ב22/07/2015 11:16 (+03:00)
-
@דוד ל.ט.
אם תשים ברייקפוינט במתודה Convert תראה שהValue תואם ל[u:igajopcy]סוג של השורה[/u:igajopcy]. ממנו תנסה להסיק בקוד רשימה מתאימה של אמצעי תשלום ולהחזיר אותם כרשימה (עם מאפיין ID כמובן לאיגוד לטבלה).
אם שמת בינדינג ללא Path מוחזר האובייקט של ההקשר (DataContext) בשלמותו. אני מבין שמדובר כעת בטבלת תרומות אז הערך אמור להיות שורה מסוג תרומה.
אין לך צורך בפניה לקומבו הראשון, אלא לערך שעליו הוא משפיע. כלומר אני מבין שהקומבו של סוג האמצעי מאוגד למאפיין מסויים [u:igajopcy]בשורת התרומה[/u:igajopcy] ממילא יש לך ביד את הערך הנוכחי.
בשביל לגשת מהמחלקה לדטה סט שהוגדר בריסורס של האפליקציה תוכל לקחת אותו ככה:Application.Current.FindResource("avrDataSet");
עדיף לעשות זאת פעם אחת בלבד אז תעשה קונסטרקטור במחלקת הממיר:
private avrDataSet avrDataSet; public WatToListWays() { avrDataSet = Application.Current.FindResource("avrDataSet"); }
פורסם במקור בפורום CODE613 ב22/07/2015 11:47 (+03:00)
-
אכן, כן מדובר על טבלה מסוג תרומות שבה מזינים תרומות חדשות.
הבעיה היא שהקומבו הקודם הוא כדי לבחור באיזה סוג אמצעי תשלום לשלם, ויש לו בינדינג לטבלה אחרת (בשם אמצעי תשלום) שבה מוזנים סוגי אמצעי התשלום (אשראי, צ'יק, מזומן, PAYPAL, העברה בנקאית). ועכשיו אני רוצה שהקומבו הבא יכיל ערכים המותאמים לערך שבחר המשתמש בקומבו של אמצעי התשלום.
כלומר, אם הוא בחר באשראי, אני רוצה שהוא יציג לו את כל כרטיסי האשראי (שנמצאים בטבלה נוספת בשם כרטיסי אשראי) המקושרים תחת השם שלו. וכן אם בחר בהעברה בנקאית או בפייפל אני רוצה שהוא יציג לו את החשבונות המקושרים לשמו מתוך אותם טבלאות.אין לך צורך בפניה לקומבו הראשון, אלא לערך שעליו הוא משפיע. כלומר אני מבין שהקומבו של סוג האמצעי מאוגד למאפיין מסויים בשורת התרומה ממילא יש לך ביד את הערך הנוכחי.
לא הבנתי מה כוונתך לערך שעליו הוא משפיע? האם לזה שלאחר שהוא בחר בקומבו הקודם באמצעי התשלום, אז שמרנו את הID שלו בתוך העמודה הקודמת, ולכן אני צריך רק לבדוק מה הערך שם?
לגבי הדטהסורס כתבתי כך (כיון שאין לי צורך בכל הדטה אלא רק בטבלאות מסוימות, האם עדיין עדיף לעשות באופן דומה למה שהצעת?)
public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { Demo de = new Demo(); var avrDS = new AvrTrumaDataSet.AshrayDataTable();//יצירת מופע חדש של טבלת נתוני האשראי int HowToPay = (int)value;//שמירת הערך המגיע מהמתודה switch (HowToPay) { case '1'://זהו הID של האשראי //שאילתא de.idMethodPayCombobox.ItemsSource = ; //קישור הקומבו להציג את נתוני השאילתא } }
אני מסתבך איך לכתוב שאילתא לדטה טייבל? האם יש מתודה מובנית (ראיתי שיש שם select , where וכדו' אבל לא הבנתי איך אני בונה שאילתא ומריץ אותה על הטבלה?
אני כרגע תוך כדי ניסיון לחפש בגוגל, אם תוכלו לעזור לי ולהסביר לי בפשטות - אשמח.
תודה רבה!!פורסם במקור בפורום CODE613 ב22/07/2015 12:07 (+03:00)
-
זה מה שהצלחתי לכתוב עד כה:
public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { Demo de = new Demo(); var avr = Application.Current.FindResource("AvrTrumaDataSet");// var ashrays = new AvrTrumaDataSet.AshrayDataTable(); int HowToPay = (int)value; switch (HowToPay) { case '1': var query = from ashray in ashrays.AsEnumerable() where ashray.IdDonor == de.donorNameCombobox//משווה את הID של בעלי הכרטיס עם הID של התורם //רק אינני מבין איך אני ניגש לID של התורם?? select ashray; foreach (var asray in ashrays) // de.idMethodPayCombobox.ItemsSource = ; //הצגת נתוני השאליתא בקומבו החדש } }
כתבת שכיון שעשיתי בינדינג לשורה אז אני פשוט ניגש לערך של השורה,
אבל אני לא מבין איך אני יכול לגשת אליו?
הרי הוא עדיין לא עידכן את הנתונים, לא?
(סליחה על הבלאגן.. לא ידעתי אם לפתוח שאלה חדשה כי זה הכל נובע מתוך אותה שאלה..)פורסם במקור בפורום CODE613 ב22/07/2015 13:19 (+03:00)
-
א. אחזור סוג התשלום, משורת תרומה.
הקומבו של הסוג מכיל רשימה זרה, אבל הבחירה של איבר ברשימה נשמרת בעמודה מקומית כל שהיא? אם כן, לעמודה זו התכוונתי.
אתה צריך לקחת את הvalue ולעשות לא קסטינג לסוג של שורת תרומה. שם יש את כל הנתונים גם מס' התורם וגם אמצעי התשלום הנבחר וכו'.ב. שאילתה. לחץ דבל קליק על הDataSet בSolution Explorer, הולך לטבלה המתאימה, קליק ימני > Add ואז Query...
באשף תבחר Select ותשתמש בבולידר בשביל התשאול. בפילטרים שים שמות עם שטרודלים למשל מס' תורם שווה ל@ID, וכן הלאה (תוכל סתם לשים סימן שאלה והוא יבחר שם אוטומטית).
אחרי שתגמור יתווסף DataAdapter מתאים עם הפרמטרים הנדרשים. הוא מחזיר טבלה ע"י המתודה GetData.הצלחה בבלגן...
זה המחיר של לימוד זריז...פורסם במקור בפורום CODE613 ב22/07/2015 13:40 (+03:00)
-
יש שתי בעיות בפתרון שלי.
א. רשימת האמצעי תשלום הקיימים היא רשימה שמוקרה ברמת השורה, כלומר לפי התרומה הנוכחית, בעוד הבינדינג של הDataGridComboBoxColumn.ItemsSource הוא ברמת הטבלה, לא ברמת השורה (כמו המאפיין Header למשל). את הבעיה הזו ניתן לפתור ע"י החלפת הDataGridComboBoxColumn בDataGridTemplateColumn ולשים בתוך הDataTemplate קומבו רגיל.
ב. הרשימה מושפעת משינוי התורם והמצעי, כלומר צירך שהיא תדע לעקוב אחרי שינויים. בעוד הבינדינג עוקב אחרי השורה כולה ולא אחרי המאפיינים הללו. גם אם נעשה מולטי בינדינג למאפיינים של התורם וסוג אמצעי, עדיין נצטרך שהמחלקה תממש עבורם INotifyPropertyChanges בשביל שהWPF יידע על שינויים. הפתרון לכך זה להרחיב את מחלקת השורה ולשים מאפיינים עם מימוש לINotify.פורסם במקור בפורום CODE613 ב23/07/2015 12:43 (+03:00)