דילוג לתוכן
  • דף הבית
  • קטגוריות
  • פוסטים אחרונים
  • משתמשים
  • חיפוש
  • חוקי הפורום
כיווץ
תחומים

תחומים - פורום חרדי מקצועי

💡 רוצה לזכור קריאת שמע בזמן? לחץ כאן!
pcinfogmachP

pcinfogmach

@pcinfogmach
אודות
פוסטים
706
נושאים
186
שיתופים
0
קבוצות
0
עוקבים
3
עוקב אחרי
1

פוסטים

פוסטים אחרונים הגבוה ביותר שנוי במחלוקת

  • איך לייצר Watermark עבור TextBox ב-wpf
    pcinfogmachP pcinfogmach

    להלן רעיון קל ליישום בשביל Watermark עבור TextBox ב-WPF באמצעות XAML בלבד:

    76b6c600-9b4f-4fe1-ae84-23997c724aa6-image.png

    (זה לא שאין ספריות והרבה כתבות על זה אבל בסופו של דבר הכל לא עבד לי חלק חוץ מהרעיון שלפניכם יש בזה גם מעלה מבחינת כך שזה מבוסס xaml בלבד)

    הסגנון מבוסס על שימוש בתכונת ToolTip של ה-TextBox לצורך הצגת ה-Watermark. כמובן שניתן להשתמש גם בתכונות אחרות (כגון Tag) – אני בחרתי ב-ToolTip, משום שכאשר מוצג Watermark, בדרך כלל אין צורך ממשי ב-Tooltip.

    בסגנון יש שני טריגרים שמאפיינים התנהגות של הסתרת ה-Watermark כאשר תיבת הטקסט בפוקוס או כאשר איננה ריקה

      <Style TargetType="TextBox" x:Key="WatermarkTextBox">
         <Setter Property="Template">
             <Setter.Value>
                 <ControlTemplate TargetType="TextBox">
                     <Border x:Name="border"
                         Background="{TemplateBinding Background}"
                         BorderBrush="{TemplateBinding BorderBrush}"
                         BorderThickness="{TemplateBinding BorderThickness}"
                         SnapsToDevicePixels="True">
                         <Grid>
                             <ScrollViewer x:Name="PART_ContentHost"
                                       Focusable="false"
                                       HorizontalScrollBarVisibility="Hidden"
                                       VerticalScrollBarVisibility="Hidden"/>
    
                             <TextBlock x:Name="PlaceholderHost" Text="{TemplateBinding ToolTip}"
                                        HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
                                        VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
                                        Padding="{TemplateBinding Padding}"
                                        Margin="{TemplateBinding Margin}"
                                        Opacity="0.2"
                                        IsHitTestVisible="False"
                                        Visibility="Collapsed"/>
                         </Grid>
                     </Border>
                     <ControlTemplate.Triggers>
                         <DataTrigger Binding="{Binding Path=Text, RelativeSource={RelativeSource Self}}" Value="">
                             <Setter Property="Visibility" TargetName="PlaceholderHost" Value="Visible"/>
                         </DataTrigger>
                         <DataTrigger Binding="{Binding Path=IsKeyboardFocusWithin, RelativeSource={RelativeSource Self}}" Value="true">
                             <Setter Property="Visibility" TargetName="PlaceholderHost" Value="Collapsed"/>
                         </DataTrigger>
                     </ControlTemplate.Triggers>
                 </ControlTemplate>
             </Setter.Value>
         </Setter>
     </Style>
    

    אפשר גם להסתיר את ה-tooltip כליל ולהשתמש רק ב-watermark במקום זאת על ידי הוספת הקוד דלהלן בתוך הסגנון.

     <Style.Resources>
         <Style TargetType="ToolTip">
             <Setter Property="Visibility" Value="Collapsed"/>
         </Style>
     </Style.Resources>
    
    תכנות

  • קודים של אתר שנבנה ללקוח, האם הוא ציבורי?
    pcinfogmachP pcinfogmach

    @צדיק-תמים כתב בקודים של אתר שנבנה ללקוח, האם הוא ציבורי?:

    אני מבין שאתה מדבר על אנשים מאוד מסוימים ולא באופן כללי, קשה לדבר על משהו שלא ברור אם כמה ואיפה קיים

    כנראה שלא נפגשתם בהתנהגות זו. ואני מתקשה לתאר לך את זה כי אתה לא מסוגל לדמיין זאת. ולכן כשאתה שומע שיש מי שמבקש כסף על משהו אתה שואל למה לא?

    בוא ניקח את הדוגמא שהביאו למעלה:
    לקחת עוד כסף על העברת הגרפיקה.
    אם כולם ככה עושים וזוהי הצורה בהחלט למה לא?
    אם אתה החלטת שכך אתה רוצה לעבוד - למה לא?
    אבל אם אתה עושה זאת בצורה ערמומית או סתם כי פתאום קלטת שאתה יכול להרוויח עוד לוקסוס על הדרך (בזמן שבתחילה בכלל לא התכוונת לקחת כסף זה מהלקוח). או ואבוי!

    תכנות

  • כיצד להשוות ערך range.Font.Color לצבע הקסדצימלי ב-VSTO?
    pcinfogmachP pcinfogmach

    @pcinfogmach כתב בכיצד להשוות ערך range.Font.Color לצבע הקסדצימלי ב-VSTO?:

    בכתבה מוצג קוד לחישוב דינאמי של הערכים השונים של גווני ערכת הנושא (בערכים דצימליים המומרים ל-hex מיוחד לוורד).

    מצו"ב הקוד מתורגם ל-C# בדגש דווקא על בהירות והבנה (במחיר זניח של יעילות).

    using System;
    using Microsoft.Office.Interop.Word;
    public class ThemeColorsHelperBase
    {
        // Color code components
        private readonly string _hexPrefix = "0x";           // Prefix used for hexadecimal strings
        private readonly string _themeColorFlag = "D";       // Identifier for theme color
        private readonly string _zeroByte = "00";            // Unused byte in the color code
        private readonly string _maxValue = "FF";            // Used when no tint/shade is applied
    
        /// <summary>
        /// Generates an int representation of a theme color with its tint or shade.
        /// </summary>
        /// <param name="themeColorIndex">Theme color index (e.g., Accent1, Text1)</param>
        /// <param name="tintAndShade">accepts percantage double (0.50, 0.25 etc.); positive (tint/lighten) or negative (shade/darken).</param>
        /// <returns></returns>
        public long GetThemeColor(WdThemeColorIndex themeColorIndex, double brightness)
        {
            string hex = GenerateThemeColorHex(themeColorIndex, brightness);
            return Convert.ToInt64(hex, 16);
        }
    
        private string GenerateThemeColorHex(WdThemeColorIndex themeColorIndex, double brightness)
        {
            string themeColorHex = ((int)themeColorIndex).ToString("X");
            string tintHex = brightness >= 0 ? ((int)((1 - brightness) * 0xFF)).ToString("X2") : _maxValue;
            string shadeHex = brightness < 0 ? ((int)((1 + brightness) * 0xFF)).ToString("X2") : _maxValue;
            string fullHex = _hexPrefix + _themeColorFlag + themeColorHex + _zeroByte + tintHex + shadeHex;
            return fullHex;
        }
    }
    
    תכנות

  • vsto תוסף לוורד: וורד גונב את הפוקוס בפקודות מסויימות
    pcinfogmachP pcinfogmach

    מצאתי פיתרון:

    Dispatcher.BeginInvoke(new Action(() =>
    {
        Keyboard.Focus(SearchTextBox);              
    }), System.Windows.Threading.DispatcherPriority.ApplicationIdle);
    

    ברוב המקרים זה עוזר אא"כ בהרצת הרבה פעולות ברצף מהיר מאוד.

    תכנות

  • איך להגדיר את ה-owner של חלון wpf בתוסף וורד
    pcinfogmachP pcinfogmach

    הקוד הבא מיועד לתוספים ב-Word המבוססים על WPF.
    הוא נועד להגדיר את חלון ה-WPF כחלון בן (Owned Window) של Word. חלון בן מתנהג באופן שונה מחלון עצמאי בכך שאינו מקבל פוקוס חוץ מחלון האב, והוא ממוזער יחד איתו. התנהגות שמצוייה בחלון דיאולוג שמקושר לחלון הפתוח. אחרת החלון יתנהל כמו תוכנה נפרדת לחלוטין מצד אופן התצוגה שלו ואף יופיע מעל חלונות של תוכנות אחרות שאינם קשורות אליו כלל.

         //יש להוסיף שם מחלקה - את שם הפרוייקט של התוסף אחרת globals לא ייקלט
    
    using System;
    using System.Diagnostics;
    using System.Windows;
    using System.Windows.Interop;
    
    public static class WordWindowOwner
    {
        public static void SetOwner(Window window)
        {
            try
            {
                var content = window.Content;
                //if (content != null) { window.Content = null; } // optional remove window content if nessecary for perfomance isssues
                IntPtr wordWindowHandle = IntPtr.Zero;
               
                var activeWindow = Globals.ThisAddIn.Application.ActiveWindow;
                wordWindowHandle = new IntPtr(activeWindow.Hwnd);
                
                WindowInteropHelper helper = new WindowInteropHelper(window);   
                helper.Owner = wordWindowHandle;
                //if (content != null) { window.Content = content; }
            }
            catch (Exception ex)
            {
                Debug.WriteLine($"Error in SetOwner: {ex.Message}");
            }
        }
    }
    
    תכנות

  • אפשרות מובנית בוורד לשלוף את כל הצבעים במסמך
    pcinfogmachP pcinfogmach

    @מד
    האמת שחשבתי על הרעיון שלך, וכשאתה מעלה אותו שוב, אני קצת משתכנע שאולי אוכל ליישם גם אותו. עם זאת, לדעתי, הוא לבדו לא משרת את המטרה.

    הסיבה היא שאם יש לך מסמך ארוך, ואינך זוכר בדיוק איזה טקסט צבוע ואיך, זה לא יהיה נוח לגלול כל פעם מחדש כדי לבצע חיפוש.
    במיוחד כאשר מדובר בהחלפות, שבהן המטרה היא לעבוד במהירות בתוך חלונית ההחלפות על מספר רב של שינויים. ואידך זיל גמור.

    תכנות

  • תוסף חיפוש רגקס בוורד
    pcinfogmachP pcinfogmach

    @dovid
    עקב דבריך הנכוחים נסיתי לבדוק זאת ואכן לא ניתקלתי במגבלה. כנראה שהיה באג בקוד שלי שגרם לבעיות אינני יודע - אולי באמת קשור לזיכרון כלומר הרבה פעולות בבת אחת. כשיהיה לי יותר מידע אכתוב בלי נדר.
    בכל אופן לבינתיים אני מסיק שאין כזו מגבלה.

    תכנות

  • באג ב-vba בפונקציה Selection.Information(wdVerticalPositionRelativeToPage)
    pcinfogmachP pcinfogmach

    @yossiz
    ייתכן שאתה צודק ואין פתרון.
    ולו יהא זה שכרי בפתיחת הפוסט שכל מורט בשער ראשו יידע מה מקור עצביו.

    אגב ההשוואה בין הטורים רק הבאתי את זה כדוגמא
    זה רלונטי לכל מיקום מדוייק של שני אובייקטים במסמך

    תכנות

  • סקיצה איך ליישם Theming ב- wpf בצורה קלה ונוחה
    pcinfogmachP pcinfogmach

    הרעיון שלי איך ליישם theming ב- wpf בצורה קלה


    שוב אני מוצא את עצמי מתמודד עם פתרונות מסורבלים. לכן יצרתי את הסקיצה הבאה עבור יישום themeing קליל פשוט ונוח (הצורך שלי היה מוגבל ל-Dark Mode, אבל ניתן להרחיב את הרעיון די בקלות).

    בבסיס האתגר הזה יש שני נושאים עיקריים:
    א. חלון WPF אינו מאפשר שינוי צבע ה-Title Bar.
    ב. יצירת Binding שיכול לשמש את כל התוכנה בצורה גלובלית.

    את עיצוב החלון כבר יצרתי בעבר, וכעת הפכתי אותו ל-Style. לדעתי, זו גישה הרבה יותר נוחה מאשר ליצור פקד חלון עם Theming, כיוון שהתעסקות עם ירושת פקד חלון ב-WPF היא קצת מורכבת. ישנם מדריכים רבים (עם הרבה באגים) בנושא, תכלס, חסכתי לכם הרבה עבודה אם זה מה שאתם מחפשים ה-style המצורף נקי ועובד חלק.

    כמה פרטים חשובים:
    ה-Style משתמש במחלקה סטטית שמארחת פקודות לסגירת חלון וכו', וגם מארחת ViewModel גלובלי. זהו פתרון קל ונוח לשימוש לצורך שינוי Theme.
    מכיוון שהצורך שלי היה ב-Dark Mode, יצרתי קוד שמזהה באופן אוטומטי אם המערכת מוגדרת ל-Dark Theme.
    בנוסף, הוספתי כפתור שמאפשר מעבר בין Dark Mode ל-Light Mode.
    עיצוב ה-Theme

    יצרתי מחלקה עם שני מאפיינים בסיסיים: Background ו-Foreground. לצרכים שלי זה היה מספיק, אבל אם אתם מחפשים משהו מורחב יותר, פשוט הוסיפו רכיבים למחלקה כיד ה' עליכם.
    Theme חדש ניתן להוסיף ל-Dictionary שנמצא ב-ViewModel, והיישום שלו אינטואיטיבי וקל.
    בנוסף, תוכלו לעשות Binding על ה-Dictionary ל-ListBox או ComboBox, ולאפשר למשתמש לבחור Theme בקלות.
    מכיוון שהמחלקה המארחת היא סטטית, תהיה לכם גישה נוחה ופשוטה ל-Themes מכל מקום בקוד.

    זהו פתרון יעיל ופשוט, ואני מאמין שיכול לחסוך לכם הרבה זמן ועבודה בהתמודדות עם אתגרי Theming ב-WPF.

    <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                        xmlns:mscorlib="clr-namespace:System;assembly=mscorlib"
                        xmlns:window="clr-namespace:MyWpf.Themes.Window;assembly=MyWpf"
                        xmlns:Converters="clr-namespace:MyWpf.Converters">
    
        <SolidColorBrush x:Key="HoverBackGroundBrush" Color="#ff646464" Opacity="0.2"/>
        <SolidColorBrush x:Key="SelectedBackGroundBrush" Color="#ff646464" Opacity="0.3"/>
        <SolidColorBrush x:Key="WindowBorderBrush" Color="#ff646464"/>
        <SolidColorBrush x:Key="TitlebarBrush" Color="#ff646464" Opacity="0.1"/>
        <mscorlib:Double x:Key="CaptionHieght">36</mscorlib:Double>
    
        <Style x:Key="TitleBarButton" TargetType="Button">
            <Setter Property="Width" Value="{Binding ActualHeight, RelativeSource={RelativeSource Mode=Self}}"/>
            <Setter Property="WindowChrome.IsHitTestVisibleInChrome" Value="True"/>
            <Setter Property="Background" Value="Transparent"/>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type Button}">
                        <Border x:Name="border" Background="{TemplateBinding Background}"
                            Padding="10">
                            <ContentPresenter x:Name="contentPresenter"/>
                        </Border>
                        <ControlTemplate.Triggers>
                            <Trigger Property="IsMouseOver" Value="true">
                                <Setter Property="Background" Value="{StaticResource HoverBackGroundBrush}"/>
                            </Trigger>
                            <Trigger Property="AreAnyTouchesOver" Value="true">
                                <Setter Property="Background" Value="{StaticResource HoverBackGroundBrush}" />
                            </Trigger>
                            <Trigger Property="IsPressed" Value="true">
                                <Setter Property="Background" Value="{StaticResource SelectedBackGroundBrush}" />
                            </Trigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    
        <Style x:Key="TitleBarPathIcon" TargetType="Path">
            <Setter Property="Stroke" Value="{Binding Foreground, RelativeSource={RelativeSource AncestorType=Window}}"/>
            <Setter Property="StrokeThickness" Value="1"/>
            <Setter Property="Stretch" Value="Uniform"/>
        </Style>
    
        <Style x:Key="DarkModeIconPath" TargetType="Path">
            <Setter Property="Fill" Value="{Binding Foreground, RelativeSource={RelativeSource AncestorType=Window}}"/>
            <Setter Property="Stretch" Value="Uniform"/>
        </Style>
    
        <Style x:Key="MaximizeRestorePath" TargetType="Path" BasedOn="{StaticResource TitleBarPathIcon}">
            <Style.Triggers>
                <!-- Trigger when Window is Maximized -->
                <DataTrigger Binding="{Binding WindowState, RelativeSource={RelativeSource AncestorType=Window}}" Value="Maximized">
                    <Setter Property="Data" Value="M 13.5,12.5 H 20.5 V 19.5 H 13.5 Z M 15.5,12.5 V 10.5 H 22.5 V 17.5 H 20.5"/>
                </DataTrigger>
    
                <!-- Trigger when Window is Normal (Not Maximized) -->
                <DataTrigger Binding="{Binding WindowState, RelativeSource={RelativeSource AncestorType=Window}}"   Value="Normal">
                    <Setter Property="Data" Value="M 13.5,10.5 H 22.5 V 19.5 H 13.5 Z"/>
                </DataTrigger>
            </Style.Triggers>
        </Style>
    
        <Style TargetType="Window" x:Key="ThemedWindow">
            <Setter Property="WindowChrome.WindowChrome">
                <Setter.Value>
                    <WindowChrome
                    CornerRadius="{x:Static SystemParameters.WindowCornerRadius}"
                    UseAeroCaptionButtons="False"
                    CaptionHeight="{StaticResource CaptionHieght}"/>
                </Setter.Value>
            </Setter>
    
            <!--<Setter Property="FlowDirection" Value="{Binding Path=(window:ThemeHelper.FlowDirection)}" />-->
            <Setter Property="Background" Value="{Binding Source={x:Static window:ThemeHelper.ThemeModel}, Path=CurrentTheme.Background}"/>
            <Setter Property="Foreground" Value="{Binding Source={x:Static window:ThemeHelper.ThemeModel}, Path=CurrentTheme.Foreground}"/>
    
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="Window">
                        <Border  BorderBrush="{StaticResource WindowBorderBrush}" 
                                 BorderThickness="0.8"
                                 Background="{TemplateBinding Background}">
                            <Grid x:Name="RootGrid">
                                <Grid.RowDefinitions>
                                    <RowDefinition x:Name="TitleBarRow" Height="auto"/>
                                    <RowDefinition x:Name="ContentRow" Height="*"/>
                                </Grid.RowDefinitions>
    
                                <Grid x:Name="TitleBarGrid"
                                      Height="{StaticResource CaptionHieght}"
                                      Background="{StaticResource TitlebarBrush}">
                                    <Grid.ColumnDefinitions>
                                        <ColumnDefinition Width="auto" x:Name="CaptionColumn"/>
                                        <ColumnDefinition Width="*" x:Name="PlaceHolderColumn"/>
                                        <ColumnDefinition Width="auto" x:Name="TitleBarButtonsColumn"/>
                                    </Grid.ColumnDefinitions>
    
                                    <TextBlock x:Name="WindowTitle" Padding="10" VerticalAlignment="Center" IsHitTestVisible="False"
                                               Text="{TemplateBinding Title}"/>
    
                                    <StackPanel x:Name="TitleBarButtonsPanel" Orientation="Horizontal" Grid.Column="2" Margin="1">
                                        <Button Style="{StaticResource TitleBarButton}"
                                                Command="{Binding Source={x:Static window:ThemeHelper.ThemeModel}, Path=ToggleThemeCommand}"
                                                CommandParameter="{Binding RelativeSource={RelativeSource AncestorType=Window}}">
                                            <Path Style="{StaticResource DarkModeIconPath}"
                                                  Data="M7.5,2C5.71,3.15 4.5,5.18 4.5,7.5C4.5,9.82 5.71,11.85 7.53,13C4.46,13 2,10.54 2,7.5A5.5,5.5 0 0,1 7.5,2M19.07,3.5L20.5,4.93L4.93,20.5L3.5,19.07L19.07,3.5M12.89,5.93L11.41,5L9.97,6L10.39,4.3L9,3.24L10.75,3.12L11.33,1.47L12,3.1L13.73,3.13L12.38,4.26L12.89,5.93M9.59,9.54L8.43,8.81L7.31,9.59L7.65,8.27L6.56,7.44L7.92,7.35L8.37,6.06L8.88,7.33L10.24,7.36L9.19,8.23L9.59,9.54M19,13.5A5.5,5.5 0 0,1 13.5,19C12.28,19 11.15,18.6 10.24,17.93L17.93,10.24C18.6,11.15 19,12.28 19,13.5M14.6,20.08L17.37,18.93L17.13,22.28L14.6,20.08M18.93,17.38L20.08,14.61L22.28,17.15L18.93,17.38M20.08,12.42L18.94,9.64L22.28,9.88L20.08,12.42M9.63,18.93L12.4,20.08L9.87,22.27L9.63,18.93Z"/>
                                        </Button>
    
                                        <Button Style="{StaticResource TitleBarButton}"
                                             Command="{Binding Source={x:Static window:ThemeHelper.MinimizeCommand}}"
                                             CommandParameter="{Binding RelativeSource={RelativeSource AncestorType=Window}}">
                                            <Path Style="{StaticResource TitleBarPathIcon}" Data="M 13,15 H 23"/>
                                        </Button>
    
                                        <Button Style="{StaticResource TitleBarButton}"
                                             Command="{Binding Source={x:Static window:ThemeHelper.MaximizeRestoreCommand}}"
                                             CommandParameter="{Binding RelativeSource={RelativeSource AncestorType=Window}}">
                                            <Path Style="{StaticResource MaximizeRestorePath}"/>
                                        </Button>
    
                                        <Button Style="{StaticResource TitleBarButton}"
                                              Command="{Binding Source={x:Static window:ThemeHelper.CloseWindowCommand}}"
                                              CommandParameter="{Binding RelativeSource={RelativeSource AncestorType=Window}}">
                                            <Path Style="{StaticResource TitleBarPathIcon}" Data="M 13,11 22,20 M 13,20 22,11"/>
                                        </Button>
    
                                    </StackPanel>
                                </Grid>
    
                                <ContentPresenter x:Name="PART_MainContentPresenter"  Grid.Row="1"/>
                            </Grid>
                        </Border>
    
                        <ControlTemplate.Triggers>
                            <Trigger Property="WindowState" Value="Maximized">
                                <Setter TargetName="RootGrid" Property="Margin" Value="7.5"/>
                            </Trigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </ResourceDictionary>
    
    using MyWpf.Models;
    using System.Diagnostics;
    using System.Windows;
    using System.Windows.Input;
    using System.Windows.Media;
    
    namespace MyWpf.Themes.Window
    {
        public static class ThemeHelper
        {
            private static ThemeModel _themeModel;
            public static ThemeModel ThemeModel
            {  
                get { if (_themeModel == null)
                        _themeModel = new ThemeModel();
                    return _themeModel; } 
            }
    
            //public static double CaptionHeight { get => SystemParameters.WindowCaptionHeight + 10;} 
            //public static FlowDirection FlowDirection { get => CultureInfo.CurrentUICulture.TwoLetterISOLanguageName == "he" ? FlowDirection.RightToLeft : FlowDirection.LeftToRight; } 
    
            public static ICommand CloseWindowCommand = new RelayCommand<System.Windows.Window>((window) => window.Close(), (window) => window != null);
            public static ICommand MaximizeRestoreCommand = new RelayCommand<System.Windows.Window>((window) => window.WindowState = window.WindowState == WindowState.Maximized ? WindowState.Normal : WindowState.Maximized, (window) => window != null);
            public static ICommand MinimizeCommand = new RelayCommand<System.Windows.Window>((window) => window.WindowState = WindowState.Minimized, (window) => window != null);
        }
    
        public class ThemeModel : ViewModelBase
        {
            private bool _isDarkTheme;
            private ThemeObject _currentTheme;
    
            public Dictionary<string, ThemeObject> ThemeCollection = new Dictionary<string, ThemeObject>
            {
                { "DarkTheme", new ThemeObject{ Background = new SolidColorBrush(Color.FromRgb(34, 34, 34)),
                                                Foreground = new SolidColorBrush(Color.FromRgb(200, 200, 200))} },
                { "LightTheme", new ThemeObject{ Background = new SolidColorBrush(Colors.White),
                                 Foreground = new SolidColorBrush(Colors.Black)} },
            };
    
            public ThemeObject CurrentTheme { get => _currentTheme; set => SetProperty(ref _currentTheme, value); }
    
            public ICommand ToggleThemeCommand => new RelayCommand<System.Windows.Window>(ToggleTheme, (window) => window != null);
    
            public ThemeModel() 
            {
                _isDarkTheme = GetSystemTheme;
                _currentTheme = _isDarkTheme ? ThemeCollection["DarkTheme"] : ThemeCollection["LightTheme"];
            }
    
            public void ToggleTheme(System.Windows.Window window)
            {
                CurrentTheme = _isDarkTheme ? ThemeCollection["LightTheme"] : ThemeCollection["DarkTheme"];
                _isDarkTheme = !_isDarkTheme;
            }
    
            static bool GetSystemTheme
            {
                get
                {
                    string registryKeyPath = @"Software\Microsoft\Windows\CurrentVersion\Themes\Personalize";
                    string registryValueName = "AppsUseLightTheme";
    
                    try
                    {
                        using (var key = Microsoft.Win32.Registry.CurrentUser.OpenSubKey(registryKeyPath))
                            if (key?.GetValue(registryValueName) is int value)
                                return value == 0; // 0 means Dark Theme is enabled, 1 means Light Theme
                    }
                    catch (Exception ex)
                    {
                        Debug.WriteLine(ex.ToString());
                    }
                    return false;
                }
            }
    
            public class ThemeObject
            {
                public SolidColorBrush Background { get; set; }
                public SolidColorBrush Foreground { get; set; }
            }
    
        }
    }
    

    הקוד משתמש בשני מחלקות שימושיות המהוות בסיס טוב עבור כל viewmodel

    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Runtime.CompilerServices;
    
    namespace MyWpf.Models
    {
        public class ViewModelBase : INotifyPropertyChanged
        {
            public event PropertyChangedEventHandler PropertyChanged;
    
            protected virtual void OnPropertyChanged(string propertyName)
            {
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
            }
    
            protected bool SetProperty<T>(ref T field, T value, [CallerMemberName] string propertyName = null)
            {
                if (EqualityComparer<T>.Default.Equals(field, value)) return false;
                field = value;
                OnPropertyChanged(propertyName);
                return true;
            }
        }
    
    }
    
    using System;
    using System.Windows.Input;
    
    namespace MyWpf.Models
    {
        public class RelayCommand : ICommand
        {
            private readonly Action _execute;
            private readonly Func<bool> _canExecute;
    
            public RelayCommand(Action execute, Func<bool> canExecute = null)
            {
                _execute = execute ?? throw new ArgumentNullException(nameof(execute));
                _canExecute = canExecute;
            }
    
            public bool CanExecute(object parameter) => _canExecute?.Invoke() ?? true;
            public void Execute(object parameter) => _execute();
    
            public event EventHandler CanExecuteChanged
            {
                add => CommandManager.RequerySuggested += value;
                remove => CommandManager.RequerySuggested -= value;
            }
        }
    
        public class RelayCommand<T> : ICommand
        {
            private readonly Action<T> _execute;
            private readonly Func<T, bool> _canExecute;
    
            public RelayCommand(Action<T> execute, Func<T, bool> canExecute = null)
            {
                _execute = execute ?? throw new ArgumentNullException(nameof(execute));
                _canExecute = canExecute;
            }
    
            public bool CanExecute(object parameter) => _canExecute?.Invoke((T)parameter) ?? true;
    
            public void Execute(object parameter) => _execute((T)parameter);
    
            public event EventHandler CanExecuteChanged
            {
                add => CommandManager.RequerySuggested += value;
                remove => CommandManager.RequerySuggested -= value;
            }
        }
    }
    
    תכנות

  • API לקבלת רשימת דפים וסימנים בספרי היסוד התורניים
    pcinfogmachP pcinfogmach

    @NH-LOCAL
    כדי להתגבר על חוסר העקביות ברמות הכותרות, אפשר להשתמש במבנה היררכי, כמו Stack, כדי לעקוב אחר ה-parent האחרון. כך ניתן לתקן את רמת הכותרת בהתאם להקשר ולהבטיח זיהוי נכון של המספרים והכותרות.

    תכנות

  • תוכנה מצוינת עם אוסף אייקונים לשימוש חינמי ב-WPF
    pcinfogmachP pcinfogmach

    אם אתם מפתחים אפליקציות ב-WPF ומחפשים אוסף אייקונים לשימוש ב-UI שלכם, מצאתי כלי מעולה שמספק אוסף גדול של אייקונים הניתנים לשימוש בקלות באמצעות תכונת ה-Path ב-XAML.

    https://apps.microsoft.com/detail/9mtbnqsz9nz9?hl=en-US&gl=US

    תכנות

  • מהו האחסון המהיר ביותר האפשרי של נתוני טקסט ב-C# ?
    pcinfogmachP pcinfogmach

    אוקיי בבדיקות שערכתי בlinqpad נראה שאתם צודקים במקסימום שהגעתי אליו היה 0.200 שניות

    תכנות

  • קוד C# לחילוץ טקסט מקבצי וורד
    pcinfogmachP pcinfogmach
    using DocumentFormat.OpenXml.Packaging;
    using System;
    using System.IO;
    using System.Runtime.InteropServices;
    using System.Text;
    using System.Xml;
    using WordInterop = Microsoft.Office.Interop.Word;
    
    namespace MsWordTextExtractor
    {
        public static class DocxTextExtractor
        {
            public static string Extract(string filePath)
            {
                try
                {
                    return ReadAllTextParts(filePath);
                }
                catch
                {
                    return WordInteropExtractor(filePath);
                }
            }
    
            static string ReadAllTextParts(string filePath)
            {
                StringBuilder stb = new StringBuilder();
                using (WordprocessingDocument wordprocessingDocument = WordprocessingDocument.Open(filePath, false))
                {
                    var mainPart = wordprocessingDocument.MainDocumentPart;
                    stb.AppendLine(ReadTextPart(mainPart.GetStream()));
    
                    if (mainPart.FootnotesPart != null)
                    {
                        string footNotes = ReadFootnotesPart(mainPart.FootnotesPart.GetStream());
                        if (!string.IsNullOrEmpty(footNotes))
                        {
                            stb.AppendLine();
                            stb.AppendLine(footNotes);
                        }
                    }
    
                    if (mainPart.EndnotesPart != null)
                    {
                        string footNotes = ReadFootnotesPart(mainPart.FootnotesPart.GetStream());
                        if (!string.IsNullOrEmpty(footNotes))
                        {
                            stb.AppendLine();
                            stb.AppendLine(footNotes);
                        }
                    }
                }
                return stb.ToString();
            }
    
            static string ReadTextPart(Stream partStream)
            {
                NameTable nameTable = new NameTable();
                XmlNamespaceManager xmlNamespaceManager = new XmlNamespaceManager(nameTable);
                xmlNamespaceManager.AddNamespace("w", "http://schemas.openxmlformats.org/wordprocessingml/2006/main");
                StringBuilder stringBuilder = new StringBuilder();
    
                XmlDocument xmlDocument = new XmlDocument(nameTable);
                xmlDocument.Load(partStream);
    
                XmlNodeList paragraphNodes = xmlDocument.SelectNodes("//w:p", xmlNamespaceManager);
                foreach (XmlNode paragraphNode in paragraphNodes)
                {
                    ReadTextContent(stringBuilder, paragraphNode, xmlNamespaceManager);
                    stringBuilder.Append(Environment.NewLine);
                }
                return stringBuilder.ToString().Trim();
            }
    
            static string ReadFootnotesPart(Stream partStream)
            {
                NameTable nameTable = new NameTable();
                XmlNamespaceManager xmlNamespaceManager = new XmlNamespaceManager(nameTable);
                xmlNamespaceManager.AddNamespace("w", "http://schemas.openxmlformats.org/wordprocessingml/2006/main");
                StringBuilder stringBuilder = new StringBuilder();
    
                XmlDocument xmlDocument = new XmlDocument(nameTable);
                xmlDocument.Load(partStream);
    
                XmlNodeList footnoteNodes = xmlDocument.SelectNodes("//w:footnote | .//w:endnote", xmlNamespaceManager);
                foreach (XmlNode footnoteNode in footnoteNodes)
                {
                    string footnoteId = footnoteNode.Attributes["w:id"].Value;
                    if (footnoteId == "-1" || footnoteId == "0") { continue; }
                    stringBuilder.Append($"{footnoteId}");
    
                    ReadTextContent(stringBuilder, footnoteNode, xmlNamespaceManager);
    
                    stringBuilder.AppendLine();
                }
                return stringBuilder.ToString().Trim();
            }
    
            static void ReadTextContent(StringBuilder stringBuilder, XmlNode xmlNode, XmlNamespaceManager xmlNamespaceManager)
            {
                XmlNodeList textNodes = xmlNode.SelectNodes(".//w:t | .//w:tab | .//w:br | .//w:footnoteReference | .//w:numPr", xmlNamespaceManager);
                foreach (XmlNode textNode in textNodes)
                {
                    switch (textNode.Name)
                    {
                        case "w:t":
                            stringBuilder.Append(textNode.InnerText);
                            break;
    
                        case "w:tab":
                            stringBuilder.Append("\t");
                            break;
    
                        case "w:br":
                            stringBuilder.Append("\v");
                            break;
    
                        case "w:footnoteReference":
                            string footnoteId = textNode.Attributes["w:id"].Value;
                            stringBuilder.Append($"{footnoteId}");
                            break;
    
                        case "w:numPr":
                            XmlNode ilvlNode = textNode.SelectSingleNode(".//w:ilvl", xmlNamespaceManager);
                            XmlNode numIdNode = textNode.SelectSingleNode(".//w:numId", xmlNamespaceManager);
                            if (ilvlNode != null && numIdNode != null)
                            {                       
                                stringBuilder.Append("*");
                            }
                            break;
                    }
                }
            }
    
            public static string WordInteropExtractor(string filePath)
            {
                string tempFilePath = Path.Combine(Path.GetTempPath(), Path.GetFileNameWithoutExtension(filePath) + ".txt");
    
    
                try
                {
                    using (WordApp wordApp = new WordApp())
                    {
                        WordInterop.Document doc = null;
                        bool isFileAlreadyOpen = false;
    
                        foreach (WordInterop.Document openDoc in wordApp.App.Documents)
                        {
                            if (openDoc.FullName.Equals(Path.GetFullPath(filePath), StringComparison.OrdinalIgnoreCase))
                            {
                                doc = openDoc;
                                isFileAlreadyOpen = true;
                                break;
                            }
                        }
    
                        if (doc == null) doc = wordApp.App.Documents.Open(filePath, ReadOnly: true, Visible: false);
    
                        var originalFormat = doc.SaveFormat;
                        doc.SaveAs2(tempFilePath, WordInterop.WdSaveFormat.wdFormatUnicodeText, Encoding: 65001, AddToRecentFiles: false);
                        if (isFileAlreadyOpen) doc.SaveAs2(filePath, originalFormat);
    
                        if (doc != null && !isFileAlreadyOpen) doc.Close(WordInterop.WdSaveOptions.wdDoNotSaveChanges);
                    }
    
                    return File.ReadAllText(tempFilePath);
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                    return string.Empty;
                }
                finally
                {
                    if (File.Exists(tempFilePath)) File.Delete(tempFilePath);
                }
            }
        }
    
        class WordApp : IDisposable
        {
            public Microsoft.Office.Interop.Word.Application App;
            bool isNewApp;
    
            public WordApp()
            {
                try
                {
                    App = (WordInterop.Application)Marshal.GetActiveObject("Word.Application");
                }
                catch (COMException)
                {
                    App = new WordInterop.Application();
                    isNewApp = true;
                }
            }
    
            public void Dispose()
            {
                if (isNewApp && App != null)
                {
                    App.Quit();
                    Marshal.ReleaseComObject(App);
                }
            }
        }
    }
    
    
    
    

    עריכה:
    מי שרוצה לחלץ טקסט מקבצי doc ללא שימוש באופיס יכול להשתמש בספרייה NPOI.HWPF

    עם הקוד דלהלן

    internal class NpoiDocExtractor
    {
        public static string ExtractTextFromDoc(string filePath)
        {
            using (FileStream fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read))
            {
                HWPFDocument doc = new HWPFDocument(fileStream);
                WordExtractor extractor = new WordExtractor(doc);
                return extractor.Text;
            }
        }
    }
    

    הספרייה עושה עבודה די טובה החסרון היחיד שלה הוא שהיא לא מחלצת את מספרי ההערות

    תכנות

  • באיזה תוכנת אינדקס גוגל משתמשים?
    pcinfogmachP pcinfogmach

    @אלף-שין
    אני מעריך את הרצון שלך להעמיק ולחקור את התחום, אך ברצוני להציע לך לשקול לא להשקיע את זמנך בדברים הללו. חקירה שטחית של נושא מורכב כמו אינדוקס ללא הבנה מעמיקה יותר עלולה לגזול זמן רב ויקר ממך ולא להביא לתוצאות הרצויות.
    בהצלחה בדרכך!

    תכנות

  • רג'קס להסרת גרשיים מטקסט מלבד ר"ת
    pcinfogmachP pcinfogmach

    אינני בקי ברגקס של JS
    אבל ב-C# הייתי עושה כך:

    ^"|"$|" | "
    

    ההחלפה קצת יותר מורכבת כי אתה צריך להיזהר לא להחליף את הרווח. ולכן ייתכן שה-lookahead וה-lookbehind עדיף במקרה הזה כמו שצדיק תמים כתב
    https://regex101.com/r/CajTc0/1

    תכנות

  • טעינה איטית של combobox מרובה פריטים ב-wpf - לא עוד!
    pcinfogmachP pcinfogmach

    לאחר שיצאתי מתוסכל מהטעינה האיטית של הפקד cmbobox כאשר יש בו הרבה פריטים חפרתי קצת ומצאתי פתרון
    מצו"ב הלינק
    https://stackoverflow.com/a/8834289

    תכנות

  • קוד להצגת שינויים בין טקסטים ב-C# (השוואת טקסטים)
    pcinfogmachP pcinfogmach

    **DiffPlex השוואת טקסטים.exe **

    למי שמעוניין בניתי את הפקד של DiffPlex בתוך חלון בצורה מסודרת (בעברית כמובן).
    עובד מעולה החיסרון היחיד שלו הוא העובדה שאין לו אפשרות לעשות wrap עבור הטקסט המוזן.

    https://github.com/mmanela/diffplex/issues/113

    שימו לב! מכיון שמדובר בתוכנה ניידת האנטי וירוס עלול למחוק אותו (תלוי איזה אנטי וירוס יש לכם).

    למי שרוצה את הקודים שמתי בגיטהאב
    https://github.com/pcinfogmach/DiffPlex-

    fbd4374e-dd66-4b72-b547-8c59853bc985-image.png

    תכנות

  • קוד להצגת שינויים בין טקסטים ב-C# (השוואת טקסטים)
    pcinfogmachP pcinfogmach

    אני יודע שיש כבר דברים מוכנים כגון אלו:
    https://github.com/mmanela/diffplex/
    http://git.savannah.gnu.org/cgit/diffutils.git/tree/src/analyze.c?id=fecd0079fe6e15b0f53bf953721d838d9099bf05

    אבל לשם ההתלמדות חשבתי לעשות אולי משהו כזה בעצמי
    הייתי שמח לקבל משוב (ההשואה יוצרת טקסט html שמסמן את השינויים)

    אגב אם מישהו מכיר תוכנה כבר מוכנה (לא אתר) אשמח לשמוע עליה

    להלן הקוד שלי

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace TextComparer
    {
        public static class TextCompare
        {
            public static void Compare(ref string text1, ref string text2)
            {
                text1 = $"<span style=\"background-color: lightblue;\">{text1}</span>";
                text2 = $"<span style=\"background-color: lightblue;\">{text2}</span>";
                // Get the LSS lss
                string lssString = "placeholdertext";
                List<string> lssList = new List<string>();
                string copyOfText1 = text1;
                string copyOfText2 = text2;
                while (!string.IsNullOrEmpty(lssString))
                {
                    try
                    {
                        lssString = FindLongestSimilarSubstring(copyOfText1.ToCharArray(), copyOfText2.ToCharArray());
                        if (lssString.Length > 1) { lssList.Add(lssString); }
                        copyOfText2 = copyOfText2.Replace(lssString, "");
                        copyOfText1 = copyOfText1.Replace(lssString, "");
                    }
                    catch { break; }
                }
    
                foreach (var item in lssList)
                {
                    text1.Replace(item, $"<span style=\"background-color: white;\"{item}");
                    text2.Replace(item, $"<span style=\"background-color: white;\"{item}");
                }
            }
    
            static string FindLongestSimilarSubstring(char[] arr1, char[] arr2)
            {
                // Initialize variables to keep track of the longest common substring
                int[,] table = new int[arr1.Length + 1, arr2.Length + 1];
                int maxLength = 0;
                int endIndex = 0;
    
                // Fill the table
                for (int i = 1; i <= arr1.Length; i++)
                {
                    for (int j = 1; j <= arr2.Length; j++)
                    {
                        if (arr1[i - 1] == arr2[j - 1])
                        {
                            table[i, j] = table[i - 1, j - 1] + 1;
                            if (table[i, j] > maxLength)
                            {
                                maxLength = table[i, j];
                                endIndex = i - 1;
                            }
                        }
                        else
                        {
                            table[i, j] = 0;
                        }
                    }
                }
    
                // Extract the longest common substring
                if (maxLength == 0)
                {
                    return ""; // No common substring found
                }
                else
                {
                    return new string(arr1, endIndex - maxLength + 1, maxLength);
                }
            }
    
        }
    }
    

    עריכה:
    לבינתיים גילית שהרעיון הנ"ל מוגבל ביותר מאחר והוא לא יכול לגלות שינויים בסדר של הקבצים מה שצריך לעשות הוא להשתמש עם lcs כמתואר כאן
    https://en.wikipedia.org/wiki/Diff
    מהשלא הצלחתי להבין הוא איך פותרים על ידי זה את הבעיה של מילים ששונה מיקומם. כי אפילו עם lcs עדיין אם יש אות זהה במיקום בו היתה המילה בראשונה אזי התוכנה תחשוב שהיא אותה האות למרות שבאמת היא שייכת למילה שהוזזה.
    בכל אופן מצו"ב הקוד הנוכחי שלי ל-lcs

     static List<string> Compare(string text1, string text2)
     {
         // Find the longest common subsequence
         List<string> commonSubsequence = LongestCommonSubsequence(text1, text2);
    
         // Generate diff output based on the longest common subsequence
         List<string> diffOutput = GenerateDiffOutput(text1, text2, commonSubsequence);
    
         return diffOutput;
     }
    
     private static List<string> LongestCommonSubsequence(string text1, string text2)
     {
         int m = text1.Length;
         int n = text2.Length;
    
         int[,] dp = new int[m + 1, n + 1];
    
         // Build DP table
         for (int i = 0; i <= m; i++)
         {
             for (int j = 0; j <= n; j++)
             {
                 if (i == 0 || j == 0)
                     dp[i, j] = 0;
                 else if (text1[i - 1] == text2[j - 1])
                     dp[i, j] = dp[i - 1, j - 1] + 1;
                 else
                     dp[i, j] = Math.Max(dp[i - 1, j], dp[i, j - 1]);
             }
         }
    
         // Reconstruct the longest common subsequence
         List<string> commonSubsequence = new List<string>();
         int index = dp[m, n];
         int temp = index;
    
         char[] lcs = new char[index + 1];
         lcs[index] = '\0';
    
         int p = m, q = n;
         while (p > 0 && q > 0)
         {
             if (text1[p - 1] == text2[q - 1])
             {
                 lcs[index - 1] = text1[p - 1];
                 p--;
                 q--;
                 index--;
             }
             else if (dp[p - 1, q] > dp[p, q - 1])
                 p--;
             else
                 q--;
         }
    
         // Convert char array to List of strings
         foreach (char c in lcs)
         {
             if (c != '\0')
                 commonSubsequence.Add(c.ToString());
         }
    
         return commonSubsequence;
     }
    
     private static List<string> GenerateDiffOutput(string text1, string text2, List<string> commonSubsequence)
     {
         List<string> diffOutput = new List<string>();
    
         int index1 = 0, index2 = 0;
         foreach (string s in commonSubsequence)
         {
             while (index1 < text1.Length && text1[index1].ToString() != s)
             {
                 diffOutput.Add($"<span style=\"background-color: rgb(255, 204, 204);\">{text1[index1]}</span>");
                 index1++;
             }
    
             while (index2 < text2.Length && text2[index2].ToString() != s)
             {
                 diffOutput.Add($"<span style=\"background-color: lightblue;\">{text2[index2]}</span>");
                 index2++;
             }
    
             diffOutput.Add($"{s}");
             index1++;
             index2++;
         }
    
         // Handle remaining parts of text1 and text2
         for (int i = index1; i < text1.Length; i++)
         {
             diffOutput.Add($"<span style=\"background-color: rgb(255, 204, 204);\">{text1[i]}</span>");
         }
    
         for (int i = index2; i < text2.Length; i++)
         {
             diffOutput.Add($"<span style=\"background-color: lightblue;\">{text2[i]}</span>");
         }
    
         return diffOutput;
     }
    
    תכנות

  • איך לזהות על ידי תוכנה קישורים בספרי קודש ?
    pcinfogmachP pcinfogmach

    @Whenever
    היעילות של קישוריות תלויה בדיוק: קישוריות איננה מנוע חיפוש אלא קפיצה קלה למיקום מסויים. אם הקפיצה נהיית מסובכת אנשים פשוט לא ישתמשו בה. אפשרות חיפוש כותרות ודאי שכבר יש בתוכנה.

    תכנות
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 13
  • 14
  • 5 / 14
  • התחברות

  • אין לך חשבון עדיין? הרשמה

  • התחברו או הירשמו כדי לחפש.
  • פוסט ראשון
    פוסט אחרון
0
  • דף הבית
  • קטגוריות
  • פוסטים אחרונים
  • משתמשים
  • חיפוש
  • חוקי הפורום