@dovid
ייתכן שהיה פה בלבול בין xaml ל-ribbon xml
לא יודע אם המושג MVVM כמות שהוא באמת שייך ליישום ב-ribbon xml
אולי צריך פה מבנה אחר אני לא בקי מספיק במבני תוכנה כדי לדעת מה המבנה הנכון פה
pcinfogmach
-
תבנית ברעיון של MVVM עבור VSTO XML RIBBON? -
הדגמה פשוטה של MVVM ב-C# WPFיש לכם הערות? אנא כתבו אותם לתועלת כולם!
הערה: אישית אני ראיתי תועלת גדולה ב-mvvm, למרות שביישום של commands לא כל כך ראיתי תועלת בפרוייקטים שלי כי לרוב זה לא היה נצרך ורק הפך את הקוד למסורבל, בכל אופן הדוגמא דלהלן כוללת אותם לצורך ההדגמה ואפשר לראות כיצד הם 'מחליקים' את פעולת התוכנה, כמו"כ הוספתי קיצורי מקשים דרך ה-commands מה שמדגים את השימושיות שלהם.
-
הדגמה פשוטה של MVVM ב-C# WPFהדגמה פשוטה של MVVM
עיין כאן להסבר על המושג MVVM:
להרחבה על הנושא עיין כאןהיה לי צורך להדגים את המודל mvvm עבור ידיד אז יצרתי את הפרוייקט דלהלן על בסיס כתבה זו (הפרוייקט רחוק מלהיות מושלם אבל הוא מספיק בשביל הדגמה לדעתי):
התוכנה מיישמת מחשבון (כלשהו) שיניתי קצת מהכתבה לצורך ההדגמה.
- קוד ל-view
<Window x:Class="WpfTestProject.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:WpfTestProject" mc:Ignorable="d" Background="WhiteSmoke" SizeToContent="WidthAndHeight" FocusManager.FocusedElement="{Binding ElementName=FirstValueTextBox}"> <Window.DataContext> <local:CalculatorViewModel/> </Window.DataContext> <Window.InputBindings> <KeyBinding Key="A" Modifiers="Control" Command="{Binding AddCommand}"/> <KeyBinding Key="S" Modifiers="Control" Command="{Binding SubTractCommand}"/> <KeyBinding Key="T" Modifiers="Control" Command="{Binding TimesCommand}"/> <KeyBinding Key="D" Modifiers="Control" Command="{Binding DivideCommand}"/> <KeyBinding Key="P" Modifiers="Control" Command="{Binding PercentCommand}"/> </Window.InputBindings> <Window.Resources> <Style TargetType="TextBox"> <Setter Property="Margin" Value="5"/> <Setter Property="HorizontalContentAlignment" Value="Center"/> <Setter Property="VerticalContentAlignment" Value="Center"/> <Setter Property="BorderBrush" Value="LightGray"/> </Style> <Style TargetType="TextBlock"> <Setter Property="Margin" Value="5"/> <Setter Property="VerticalAlignment" Value="Center"/> </Style> <Style TargetType="Label"> <Setter Property="Margin" Value="5"/> <Setter Property="HorizontalContentAlignment" Value="Center"/> <Setter Property="VerticalContentAlignment" Value="Center"/> <Setter Property="BorderBrush" Value="LightGray"/> <Setter Property="BorderThickness" Value="1"/> <Setter Property="Background" Value="White"/> </Style> <Style TargetType="Button"> <Setter Property="Margin" Value="5"/> <Setter Property="Background" Value="{x:Null}"/> <Setter Property="BorderBrush" Value="LightGray"/> <Setter Property="Height" Value="38"/> <Setter Property="Width" Value="{Binding Path=Height, RelativeSource={RelativeSource Self}}"/> </Style> </Window.Resources> <StackPanel> <TextBlock Text="Calculator" HorizontalAlignment="Center" FontSize="34" Foreground="BlueViolet"/> <Grid Margin="5,10,5,5" KeyboardNavigation.TabNavigation="Cycle"> <Grid.ColumnDefinitions> <ColumnDefinition Width="*"/> <ColumnDefinition Width="auto"/> <ColumnDefinition Width="*"/> <ColumnDefinition Width="auto"/> <ColumnDefinition Width="*"/> </Grid.ColumnDefinitions> <TextBox x:Name="FirstValueTextBox" Grid.Column="0" Text="{Binding FirstValue}" /> <TextBlock Text="{Binding MathMethod}" Grid.Column="1"/> <TextBox x:Name="SecondValueTextBox" Grid.Column="2" Text="{Binding SecondValue}"/> <TextBlock Text="=" Grid.Column="3" VerticalAlignment="Center" Margin="5"/> <Label Grid.Column="4" Margin="5" Content="{Binding ResultValue, BindsDirectlyToSource=True}"/> </Grid> <StackPanel Orientation="Horizontal" Margin="5"> <Button Content="+" Command="{Binding AddCommand}"/> <Button Content="-" Command="{Binding SubTractCommand}"/> <Button Content="*" Command="{Binding TimesCommand}"/> <Button Content="/" Command="{Binding DivideCommand}"/> <Button Content="%" Command="{Binding PercentCommand}"/> </StackPanel> </StackPanel> </Window>
- קודים המהווים בסיס ל-viewmodel
using System; using System.Windows.Input; namespace WpfTestProject { public abstract class ICommandBase : ICommand { public event EventHandler CanExecuteChanged; public virtual bool CanExecute(object parameter) { return true; } public abstract void Execute(object parameter); protected void OnCanExecuteChanged() { CanExecuteChanged?.Invoke(this, new EventArgs()); } } public class RelayCommand : ICommandBase { private Action commandTask; public RelayCommand(Action action) { commandTask = action; } public override void Execute(object parameter) { commandTask(); } } } public class INotifyPropertyChangedBase : INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; protected void OnPropertyChanged(string propertyName) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } }
- ה-viewmodel
using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Input; namespace WpfTestProject { public class CalculatorViewModel : INotifyPropertyChangedBase { #region members string _mathMethod; double _firstValue; double _secondValue; double _result; #endregion #region properties public string MathMethod { get => _mathMethod; set { _mathMethod = value; OnPropertyChanged(nameof(MathMethod)); } } public double FirstValue { get => _firstValue; set => _firstValue = value; } public double SecondValue { get => _secondValue; set => _secondValue = value; } public double ResultValue { get => _result; set { _result = value; OnPropertyChanged(nameof(ResultValue)); } } #endregion #region Commands public ICommand AddCommand { get { //return plusCommand; return new RelayCommand(Add); } } public ICommand SubTractCommand { get { return new RelayCommand(SubTract); } } public ICommand TimesCommand { get { return new RelayCommand(Times); } } public ICommand PercentCommand { get { return new RelayCommand(Percent); } } public ICommand DivideCommand { get { return new RelayCommand(Divide); } } #endregion #region Methods public void Add() { MathMethod = "+"; ResultValue = FirstValue + SecondValue; return; } public void SubTract() { MathMethod = "-"; ResultValue = FirstValue - SecondValue; } public void Times() { MathMethod = "*"; ResultValue = FirstValue * SecondValue; } public void Divide() { MathMethod = "/"; ResultValue = FirstValue / SecondValue; } public void Percent() { MathMethod = "%"; ResultValue = FirstValue * SecondValue; } #endregion } }- שמתם לב? ה-model חסר.... בתוכנה זו לא היה צורך ב-model בעיקרון ה-model היה יכול להיות אחד משני דברים. או class עם מבנה נתונים. או class עם קוד חיצוני.
-
טעינה איטית של combobox מרובה פריטים ב-wpf - לא עוד!לאחר שיצאתי מתוסכל מהטעינה האיטית של הפקד cmbobox כאשר יש בו הרבה פריטים חפרתי קצת ומצאתי פתרון
מצו"ב הלינק
https://stackoverflow.com/a/8834289 -
איך ליצר קיצור מקשים בוורד עבור קודים ב-C# VSTOיש כמה דרכים לעשות זאת כאן אכתוב את הבסיס איך לעשות זאת על ידי הוספת קוד vba('רך אחרת תוכלו לראות פה)
אפשר לשכלל את זה כמובן אני רק כותב את הבסיס שאם מישהו יצטרך שלא יתחיל מאפס
- יצירת קלאס ב-C#: בקוד C# יש ליצור class ולהוסיף לו את התג ComVisible(true) כדי לאפשר ל-Microsoft Office לגשת אליו דרך COM. לשם הדוגמה בתוך הקלאס נגדיר פונקציה פשוטה בשם GetNumber שמחזירה את המספר 42.
[ComVisible(true)] public class MyManagedFunctions { public int GetNumber() { return 42; } }- קוד עבור ה-startup של התוסף: בקוד ה-C# הוא נכתב תחת אירוע ה-startup של התוסף. בעת ה-startup, הקוד מפעיל את הפונקציה RegisterCallback עם אינסטנס של ה-class שנוצר בצעד הקודם. בנוסף, הקוד מצריך תגובה לאירוע של פתיחת מסמך חדש (DocumentOpen). כאשר מסמך נפתח, הקוד מפעיל פונקציה נוספת (Application_DocumentOpen) בו אפשר לקרוא לקודים של המאקרו דלהלן שאחראיים על חיבור או הסרת הקיצורי מקשים לפונקציה.
private void ThisAddIn_Startup(object sender, System.EventArgs e) { this.Application.Run("RegisterCallback", new MyManagedFunctions()); this.Application.DocumentOpen += Application_DocumentOpen; } private void Application_DocumentOpen(Microsoft.Office.Interop.Word.Document Doc) { //this.Application.Run("AssignShortcut"); // Run the VBA macro to assign the shortcut //this.Application.Run("RemoveShortcut"); // Run the VBA macro to remove the shortcut this.Application.DocumentOpen -= Application_DocumentOpen; }- קוד בשביל ה-מאקרו VBA: הקוד ב-VBA מגיב לפעולות של המשתמש בתוכניות כמו Word. הוא כולל כמה פונקציות:
RegisterCallbackשמקבלת אובייקט ומגדירה אותו למשתנהmanagedObject,
ו-GetNumberFromVSTOשמפעילה את הפונקציהGetNumberמה-C# ומציגה את התוצאה ב-MessageBox.
יש גם פונקציות להקצאת קיצורי מקלדת (AssignShortcutו-RemoveShortcut) ופונקציה (RemoveAllShortcuts) להסרת כל הקיצורי מקלדת.
ו-ShowAllShortcutKeys- למקרה ששחכתם מה עשיתם בעבר
Dim managedObject As Object Public Sub RegisterCallback(callback As Object) Set managedObject = callback End Sub Public Function GetNumberFromVSTO() As Integer GetNumberFromVSTO = managedObject.GetNumber() MsgBox "The number is " & GetNumberFromVSTO End Function Sub CallVstoFunction() Call GetNumberFromVSTO End Sub Public Sub AssignShortcut() ' Assign Ctrl+Shift+Q to CallVstoFunction CustomizationContext = NormalTemplate KeyBindings.Add KeyCode:=BuildKeyCode(wdKeyControl, wdKeyShift, wdKeyQ), _ KeyCategory:=wdKeyCategoryMacro, _ Command:="CallVstoFunction" End Sub Public Sub RemoveShortcut() ' Remove the shortcut key assignment for CallVstoFunction Dim keyBinding As keyBinding For Each keyBinding In KeyBindings If keyBinding.Command = "Normal.Module1.CallVstoFunction" Then keyBinding.Clear End If Next keyBinding End Sub Public Sub RemoveAllShortcuts() ' Remove the shortcut key assignment CustomizationContext = NormalTemplate KeyBindings.ClearAll End Sub Sub ShowAllShortcutKeys() Dim keyBinding As keyBinding Dim msg As String msg = "Currently assigned shortcut keys:" & vbCrLf For Each keyBinding In Application.KeyBindings msg = msg & "Command: " & keyBinding.Command & ", Key: " & keyBinding.KeyString & vbCrLf Next keyBinding MsgBox msg End Subלפעמים צריך להתחיל את וורד מחדש כדי שהקודים 'ייתפסו'
-
מאוורר שהתחיל להסתובב לאט - מה עושים@אף-אחד-3
כל מילה בסלע!
רק רציתי להוסיף שהרבה פעמים נתקע שעות וכיו"ב שם בפנים ואם כבר עושים גירוז אז להסיר כמובן את כל הליכלוכים -
קוד להצגת שינויים בין טקסטים ב-C# (השוואת טקסטים) -
תבנית ברעיון של MVVM עבור VSTO XML RIBBON?@dovid
אה
הייתרון לעניין הסדר הוא העובדה שאני מפריד את המתודות של ה-פעולות משאר המתודות שלא נוגעות לפעולות אלא ל-view
כאשר יש מאות לחצנים זה מאוד משמעותי -
התייחסות דינמית ל-Globals בקוד VSTO במאגר משותף?אני מנסה ליצור מאגר של קודים שימושיים ל-VSTO (Visual Studio Tools for Office). הבעיה היא שאני צריך להתייחס ל-Globals של התוסף, וזה ספציפי ל-namespace שלו. המשמעות היא שאם אני אשתף את המאגר עם מישהו אחר, הוא ייתקל באלף שגיאות ויצטרך להחליף את כל ההתייחסויות ל-Globals בכל הקוד.
האם יש דרך לזהות את ה-Globals בצורה דינמית בהתאם לאפליקציה, כך שזה לא משנה באיזה namespace הם נמצאים?
-
תבנית ברעיון של MVVM עבור VSTO XML RIBBON?@dovid
תודה על המשוב. אתה צודק כמובן, זה לא נעשה כמו שצריך.
למעישה אני מחפש סדר בקוד
אשמח לשמוע רעיונות. -
תבנית ברעיון של MVVM עבור VSTO XML RIBBON?לאחרונה יצא לי לעבוד על פרויקט עם הרבה לחצנים בסרגל הכלים של וורד. אמרתי לעצמי שזה לא שפוי ואני חייב לעשות סדר בבלאגן באמצעות חלוקה למשהו כמו-MVVM (Model-View-ViewModel).
מכיון שה-ribbon xml לא באמת נותן גישה לאוסף של הפקדים חשבתי על הרעיון הבא:
הרעיון הוא לקרוא לכל מתודה על ידי ID של הלחצן באותו שם, ולהעביר את הלוגיקה הקשורה ללחיצה על הלחצן לתוך class נפרד ומסודר, מה שיעשה את הקוד יותר נקי וניתן לניהול.
(עוד לא יישמתי את הרעיון לגבי אייקונים אבל שם זה אמור להיות ממש עוצמתי מאחר ובצורה הזו כל מה שהמשתמש יצטרך לעשות זה להוסיף אייקון לפרוייקט ולקרוא לו בשם של הכפתור).
להלן דוגמאות עבור button1 ו-button2.
בתוך ה-callbacks יש להוסיף את הקודים הבאים:
private ButtonInvoker buttonInvoker; public Ribbon() { buttonInvoker = new ButtonInvoker(); }public void button_Click(Office.IRibbonControl control) { buttonInvoker.InvokeButtonMethod(control.Id); }במקום ליצור מתודה ייחודית לכל כפתור ב-XML, כל כפתור יקרא לאותה מתודה. הנה דוגמה ל-XML:
xml <?xml version="1.0" encoding="UTF-8"?> <customUI onLoad="Ribbon_Load" xmlns="http://schemas.microsoft.com/office/2006/01/customui"> <ribbon> <tabs> <tab id="tab1" label="Label"> <group id="MyCustomGroup" label="My Custom Group"> <button id="button1" label="Button 1" onAction="button_Click"/> <button id="button2" label="Button 2" onAction="button_Click"/> </group> </tab> </tabs> </ribbon> </customUI>כעת, נוסיף את מחלקת ה-ButtonInvoker שתטפל בלחצנים:
public class ButtonInvoker { public void InvokeButtonMethod(string methodName) { try { MethodInfo method = this.GetType().GetMethod(methodName, BindingFlags.NonPublic | BindingFlags.Instance); if (method != null) { method.Invoke(this, null); } else { MessageBox.Show($"No method found for button ID: {methodName}"); } } catch (Exception ex) { MessageBox.Show($"Error invoking method for button ID: {methodName}. Error: {ex.Message}"); } } private void button1() { MessageBox.Show("Button 1 clicked"); } private void button2() { MessageBox.Show("Button 2 clicked"); } }בעזרת הקוד הזה, הצלחנו לפשט את ניהול הלחצנים בסרגל הכלים של וורד ולהקטין את הבלאגן. כל לחצן מזוהה לפי ה-ID שלו וקורא לאותה מתודה כללית שמפעילה את המתודה המתאימה בהתאם ל-ID.
-
קוד להצגת שינויים בין טקסטים ב-C# (השוואת טקסטים) -
עזרה עם בעיה בהתחברות לגיטהב@קומפיונט
תודה רבה!
עזרת לי מאוד! -
קוד להצגת שינויים בין טקסטים ב-C# (השוואת טקסטים)**DiffPlex השוואת טקסטים.exe **
למי שמעוניין בניתי את הפקד של DiffPlex בתוך חלון בצורה מסודרת (בעברית כמובן).
עובד מעולה החיסרון היחיד שלו הוא העובדה שאין לו אפשרות לעשות wrap עבור הטקסט המוזן.https://github.com/mmanela/diffplex/issues/113
שימו לב! מכיון שמדובר בתוכנה ניידת האנטי וירוס עלול למחוק אותו (תלוי איזה אנטי וירוס יש לכם).
למי שרוצה את הקודים שמתי בגיטהאב
https://github.com/pcinfogmach/DiffPlex-
-
עזרה עם בעיה בהתחברות לגיטהב@shraga
לפי מה שכתוב שם המתקין החדש אמור לטפל בזה באופן אוטומטי
למעישה התקנתי שוב ולא עזר
לפנות לנטפרי? -
קוד להצגת שינויים בין טקסטים ב-C# (השוואת טקסטים)@צדיק-תמים
על פניו זה נראה שהוא רק משווה מסמכים, לא טקסטים מוזנים? -
עזרה עם בעיה בהתחברות לגיטהבאני מנסה לעזור למישהו עם הפקוייקט שלו בגיט האב הוא שיתף אותי בפרוייקט
אבל כל פעם שאני מנסה לעשות cloning אני נתקל בשגיאה דלהלן

-
קוד להצגת שינויים בין טקסטים ב-C# (השוואת טקסטים)@צדיק-תמים
תודה
ראיתי את זה נראה ממש יפה
אבל זה לא בעברית