Задать вопрос
Ответы пользователя по тегу C#
  • На сколько практично разделять логику загрузки данных?

    VoidVolker
    @VoidVolker Куратор тега JavaScript
    Dark side eye. А у нас печеньки! А у вас?
    "Правильность" зависит от точки зрения, требований, ограничений и прочих особенностей решения. Ваш код решает вашу проблему? Удовлетворяет вашим требованиям, предъявляемым к нему? Значит всё отлично. Если нет - то тут уже надо думать и искать более правильное решение по конкретным критериям конкретного проекта.
    Ответ написан
    Комментировать
  • Как настроить полосу прокрутки, чтобы срабатывала только при наведении на неё?

    VoidVolker
    @VoidVolker Куратор тега C#
    Dark side eye. А у нас печеньки! А у вас?
    Через перехват оконного сообщения WM_MOUSEWHEEL на уровне окна и проверку либо координат курсора (над полосой он прокрутки или нет), либо, что правильнее в вашем случае - проверять нажат ли контрол или нет (т.е. масштабирование это или нет):
    public class MyForm : Form
    {       
        protected override void WndProc(ref Message m)
        {           
            if(m.Msg == WM_MOUSEWHEEL) 
            {
                // ...
                return;
            }; 
            base.WndProc(ref m);
        }
    }
    Ответ написан
    Комментировать
  • Как правильно добавить переменную?

    VoidVolker
    @VoidVolker Куратор тега C#
    Dark side eye. А у нас печеньки! А у вас?
    - int izgib = random.Next(izi_ot, izi_do);
    + double izgib = random.Next(izi_ot, izi_do)/10.0;
    Ответ написан
    2 комментария
  • Zenject зачем добавлять к SceneLoader наследование от ISceneLoader?

    VoidVolker
    @VoidVolker Куратор тега C#
    Dark side eye. А у нас печеньки! А у вас?
    Затем, что интерфейс реализует какой-то определённый функционал. Если класс не реализует интерфейс - то и использовать функционал интерфейса не получится.

    Zenject зачем добавлять к SceneLoader наследование от ISceneLoader

    Для реализации данного интерфейса, чтобы который потом кто-то мог использовать.

    чтобы потом указывать ISceneLoader как тип

    Нет, чтобы работать конкретно с функционалом данного интерфейса.

    хотя если указать просто SceneLoader как тип ничего не изменится

    Изменится: данный интерфейс будет недоступен. Да, можно объявить одноименные функции, поля и свойства, но интерфейсом это уже не будет. И, соответственно, те, кому нужен будет именно этот интерфейс не сможет его использовать, т.к. класс не реализует данный интерфейс.

    Например, у вас может быть группа разных класса реализующих определённый интерфейс. И вам надо что-то сделать с несколькими экземплярами этих нескольких классов. Можно для каждого сделать по переменной и отдельно для каждого сделать нужную операцию. А можно сделать список интерфейсов и спокойно работать с объектами через интерфейс. Аналогично и для всех других применений. Интерфейс - это прежде всего соглашение о реализации какого-то определённого функционала и его использование.
    Пример кода
    public interface IFoo
    {
        public string Name { get; set; }
    }
    
    public class Bar1(string name) : IFoo
    {
        public string Name { get; set; } = name;
    }
    
    public class Bar2(string name) : IFoo
    {
        public string Name { get; set; } = name;
    }

    List<IFoo> list = [
        new Bar1("Bar 1"),
        new Bar2("Bar 2")
    ];
    
    foreach (IFoo foo in list)
    {
        Console.WriteLine(foo.Name);
    }

    Результат:
    Bar 1
    Bar 2

    Вообще, рекомендую почитать литературу про ООП и интерфейсы в частности. Например: https://metanit.com/sharp/tutorial/3.9.php
    Ответ написан
    Комментировать
  • Как правильно извлечь из БД Uri для отображения картинки в DataGrid (C# WPF)?

    VoidVolker
    @VoidVolker Куратор тега C#
    Dark side eye. А у нас печеньки! А у вас?
    public System.Windows.Media.ImageSource Source { get; set; }

    https://learn.microsoft.com/en-us/dotnet/api/syste...
    Ну и у вас в коде же правильное решение:

    TestImage2.Source = new BitmapImage(LoadedUri);

    Т.е., вам надо конвертер не в Uri, а в тип BitmapImage. Ну или просто завести сразу свойство нужного типа.

    Кроме того, вот тут у вас ошибка во втором параметре конвертера, который противоречит касту:
    var LoadedUri = (Uri)stringToUriConverter.Convert(a, typeof(BitmapImage), null, CultureInfo.CurrentCulture);


    Там должен быть тип в который происходит конвертация. Ну и вообще конвертер лучше реализовывать полностью со всеми проверками и типами.
    Ответ написан
    1 комментарий
  • Как добавить данные из БД в отредактированный DataGrid (C# WPF)?

    VoidVolker
    @VoidVolker Куратор тега C#
    Dark side eye. А у нас печеньки! А у вас?
    DataGrid -> Properties -> AutoGenerateColumns
    А вообще, дата-грид и многие другие сложные контролы в WPF - то ещё веселье. Посмотрите в сторону AvaloniaUI. Ну а если всё же захотите сделать что-то чуть сложнее стандартных примеров из мана со стандартными контролами - то их шаблоны всё равно придётся переделывать, а местами реализовывать тот же функционал, но работающий правильно, а не в стиле индусов. Вот как-то так, например: GridTable.cs - таблица на базе обычного Grid с добавленными свойствами шаблонов для заголовков и ячеек, а так же своим движком для рендернинга таблицы (строк, столбцы, заголовки).
    Ответ написан
    2 комментария
  • Как исправить ошибку CS0019 в Unity?

    VoidVolker
    @VoidVolker Куратор тега C#
    Dark side eye. А у нас печеньки! А у вас?
    Написано же, что складывать текст и флоат нельзя. Очевидно, что вы тут перепутали переменные. Думаю, вполне ясно, что вместо текстовой тут должна быть другая переменная?
    Ответ написан
    2 комментария
  • Как распознать клавишу Alt в терминале?

    VoidVolker
    @VoidVolker Куратор тега C#
    Dark side eye. А у нас печеньки! А у вас?
    Learn / Windows / Apps / Win32 / API / Keyboard and Mouse Input / Winuser.h / GetKeyState():
    https://learn.microsoft.com/en-us/windows/win32/ap...
    Ответ написан
    Комментировать
  • Как правильно обрабатывать исключения в WPF приложении?

    VoidVolker
    @VoidVolker Куратор тега C#
    Dark side eye. А у нас печеньки! А у вас?
    1. Да, надо. Нет, все исключения в Main поймать нельзя.
    2. Есть несколько вариантов:
      1. Сообщение в стандартном WPF контроле в рамках основного окна (типа стандартного сообщения или всплывающего контрола).
      2. Стандартное WinAPI сообщение.
      3. Отдельное окно с WPF контролом и деталями сообщения.
    3. Да, вполне нормальный вариант.

    В целом же, стандартный подход выглядит примерно так:
    • Создаём несколько категорий исключений для разных ситуаций (условно - диск, приложение, загрузка, скачивание, сеть и т.п.)
    • В каждой категории создаём несколько типов исключений, наследуя их от класса Exception и указывая параметры исключений
    • На верхнем уровне ловим исключения, для каких-то определённых типов исключений можно добавлять отдельные ветки
    • В обычных условиях просто выкидываем исключение, которое будет поймано на верхнем уровне
    • В нестандартных условиях ловим на месте или показываем сообщение об ошибке с ожиданием

    Это позволяет по типу или идентификатору исключения определить точное место, где это исключение произошло, а так же отделить свои исключения от чужих. Ну и плюс есть какой-то отдельный класс с методами для показа сообщений, ошибок и вопросов с возможностью вызвать его где и как угодно.

    Реальный пример базового класса для исключения с локализацией:
        /// <summary>
        /// Localized exception
        /// </summary>
        /// <param name="stringId">i18n string Id</param>
        /// <param name="args">String arguments for format</param>
        public class I18nException(string stringId, object[] args)
            : Exception(
                string.Format(
                    I18n($"{ExceptionId} {stringId}"),
                    args))
        {
            public readonly object[] Args = args;
            public readonly string StringId = stringId;
            private const string ExceptionId = "Exception";
        }

    I18n(string str) - функция для получения локализованной строки для текущего языка приложения.
    Ну и далее наследуем свои исключения от этого базового типа:
        public class ElementNotFoundException(Type type, string name)
            : I18nException(
                "Element not found",
                [type.FullName, name]
            )
        {
            public readonly string ElementName = name;
            public readonly Type ElementType = type;
        }
    (тыц).
    Ответ написан
    2 комментария
  • Как влиять на окно выводя его за пределы экрана?

    VoidVolker
    @VoidVolker Куратор тега C#
    Dark side eye. А у нас печеньки! А у вас?
    Сравнить координаты и размеры окна с координатами и размером текущего экрана.
    Ответ написан
    Комментировать
  • Какой самый быстрый способ поиска файлов на сетевом диске?

    VoidVolker
    @VoidVolker Куратор тега C#
    Dark side eye. А у нас печеньки! А у вас?
    Использовать индексацию на стороне сервера.
    А для решения проблемы скорости вашего кода вам следует провести его диагностику, найти узкие места и устранить их.
    Ответ написан
  • Как сделать мультиплатформенный проект c# используя Visual Studio?

    VoidVolker
    @VoidVolker Куратор тега C#
    Dark side eye. А у нас печеньки! А у вас?
    Просто создаёте кроссплатформенный .Net 9 проект и добавляете профили публикации для разных ОС. Далее под виндой делаете сборку для винды, а под линуксом соответственно делаете сборку для линукса с использованием этих самых профилей. Если вам нужна графическая оболочка - то отличным выбором будет что-то типа Avalonia. Для платформенно-зависимого кода используйте стандартные директивы препроцессора. Если вы хотите для разных платформ использовать разные фреймворки/библиотеки, есть много кода для разных платформ или сложные зависимости, то в этом случае удобнее сделать три проекта: по отдельному проекту для каждой платформы и третий зависимый проект в виде библиотеки с общим для всех платформ кодом.
    Ответ написан
  • Как работают переводы на другие языки в играх?

    VoidVolker
    @VoidVolker Куратор тега C#
    Dark side eye. А у нас печеньки! А у вас?
    перевод игры лежит в отдельном файле(например json и хранит в себе каждую строчку текста, которая применяется в игре), и потом в коде запрашивать нужную строку из файла и брать от туда значение текста для последующего применения на сцене

    Да, так оно и работает.

    или есть способы попроще

    Проще уже некуда.
    Ответ написан
    4 комментария
  • Как реализовать массив хранящий различные типы данных?

    VoidVolker
    @VoidVolker Куратор тега C#
    Dark side eye. А у нас печеньки! А у вас?
    Именно массив с любыми типами вот так можно сделать:
    object[] foo = { "Abc", 123 };
    А на картинке у вас уже массив объектов со своими свойствами (в соседнем ответе пример привели уже).
    Ответ написан
  • В чем смысл public _ {get;set} в c#?

    VoidVolker
    @VoidVolker Куратор тега C#
    Dark side eye. А у нас печеньки! А у вас?
    Есть поля и есть свойства. Доступ к свойству осуществляется через методы - получения, записи, добавления или вычитания свойства. У полей нет отдельных методов доступа - используется только стандартный механизм доступа. RTFM:
    classes and structs -> fields
    classes and structs -> properties
    Ответ написан
    Комментировать
  • Почему такая ошибка в скрипте и как её исправить?

    VoidVolker
    @VoidVolker Куратор тега C#
    Dark side eye. А у нас печеньки! А у вас?
    Там же написано, что это метод, а не свойство или поле. Да и из названия это вполне очевидно. А ещё есть и всплывающая подсказка, в которой тоже будет написано.
    Ответ написан
  • Как узнать ClientSize окна в wpf приложения?

    VoidVolker
    @VoidVolker Куратор тега C#
    Dark side eye. А у нас печеньки! А у вас?
    Если вам именно самого окна в нормальных координатах, то можно использовать WinApi:
    https://github.com/VoidVolker/LockScreen/blob/mast...
    public static class Native
    {
        [DllImport("user32.dll")]
        private static extern bool GetWindowRect(IntPtr hwnd, ref RECT rectangle);
    
        [DllImport("user32.dll")]
        private static extern bool GetClientRect(IntPtr hwnd, ref RECT rectangle);
    
        public RECT GetWindowPos(IntPtr hwnd)
        {
            var r = new RECT();
            GetWindowRect(hwnd, ref r);
            return r;
        }
    
        public RECT GetClientPos(IntPtr hwnd)
        {
            var r = new RECT();
            GetClientRect(hwnd, ref r);
            return r;
        }
    
        [Serializable]
        [StructLayout(LayoutKind.Sequential)]
        public struct RECT(int left, int top, int right, int bottom)
        {
            public int Left = left;
            public int Top = top;
            public int Right = right;
            public int Bottom = bottom;
            public readonly int Width => Right - Left;
            public readonly int Height => Bottom - Top;
        }
    }

    Значения RenderSize и ActualWidth/ActualHeight будут после вычисления положения самого элемента. Скорее всего вы слишком рано пытаетесь получить к ним доступ. Запустите ваше приложение и в отладчике посмотрите в дереве окон значения.
    Плюс учтите, что в WPF свои пиксели, которые надо конвертировать в нормальные и обратно с учётом DPI текущего монитора, на котором располагается окно (на SO есть готовый код). И из-за этого WPF окно невозможно 100% точно позиционировать в нужных координатах и нужного размера в многомониторной конфигурации.

    Пример работы с визуалом элемента при его инициализации:
    public class MyControl : Control
    {
        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();
            // Размеры и позиция элемента вычислены и он готов к работе
        }
    }

    https://github.com/VoidVolker/LockScreen/blob/mast... - пример из реального проекта.
    Т.е., наследуете свой элемент от базового класса или любого другого элемента и вклиниваетесь в событие применения шаблона элемента. В разметке XAML добавляете ссылку на класс и спокойно используете свой элемент как обычно.
    Ответ написан
    Комментировать
  • Можно ли получить значение свойства, прототип которого помечен в интерфейсе атрибутом?

    VoidVolker
    @VoidVolker Куратор тега C#
    Dark side eye. А у нас печеньки! А у вас?
    using System.Reflection;
    
    namespace ConsoleAppTest
    {
        public static class Program
        {
            private static void Main(string[] args)
            {
                Test obj = new() { Prop1 = "Prop1 Value" };
                // Получаем тип объекта
                Type objType = typeof(Test);
                // Получаем список интерфейсов
                Type[] interfaces = objType.GetInterfaces();
                foreach (Type iface in interfaces)
                {
                    // Получаем список свойств интерфейса
                    PropertyInfo[] ifaceProperties = iface.GetProperties();
                    foreach (PropertyInfo prop in ifaceProperties)
                    {
                        // Ищем нужный аттрибут в свойстве
                        Attribute? attribute = prop.GetCustomAttribute<TestAttribute>();
                        if (attribute != null)
                        {
                            // Получаем значение свойства
                            object? propValue = prop.GetValue(obj); // -> Prop1 Value
                        }
                    }
                }
            }
        }
        
        [AttributeUsage(AttributeTargets.Property)]
        public sealed class TestAttribute : Attribute
        { }
    
        internal sealed class Test : ITest
        {
            public string Prop1 { get; set; } = string.Empty;
        }
    
        internal interface ITest
        {
            [Test]
            public string Prop1 { get; set; }
        }
    }
    Ответ написан
  • Как реализовать на C# интерфейс программы не просто кнопки на wpf или winForms?

    VoidVolker
    @VoidVolker Куратор тега C#
    Dark side eye. А у нас печеньки! А у вас?
    WPF/MAUI позволяет рисовать любые интерфейсы с любыми эффектами. Да, можно кинуть элемент на форму, но возможности формошлёпа ограничены, поэтому обычно пишут кодом, а формошлёпы полезны для прототипов и нубов. В WPF/MAUI стандарт - MVVM паттерн и плюс ещё несколько других вариантов есть. На хабре поищите статьи про него и библиотеку Prism (рекомендую) - там есть очень хорошие и подробные статьи. Интерфейс описывается с помощью XML, а именно - XAML. Да, оно не идеально, для маленьких проектов не очень практично, хоть и вполне применимо. А вот в средних и больших/сложных проектах - отличное решение, особенно в команде.

    WinForms сегодня имеет смысл использовать только если вам нужна поддержка специфических функций, Windows XP или просто хотите по-быстрому наформошлёпить что-то маленькое и одноразовое. В остальном признано устаревшей технологией и применяется только как дополнение или костыль для исправления костылей WPF. Да, в WPF тоже есть костыли и они очень хорошо чувствуются и с которыми приходится бороться (например невозможность абсолютно точного позиционирования WPF окна на мультимониторной конфигурации из-за костылей в механизмах DPI винды и WPF).

    Ну и плюс отдельного упоминания заслуживают альтернативные UI библиотеки и фреймворки типа Avalonia, Uno и иже с ними.

    Вот вам несколько реальных примеров реализации дизайнерских интерфейсов:
    WPF custom GUI
    900181ba79.png
    2791f5a63c.png
    71ab1f8462.png

    Вот тут можно посмотреть исходный код небольшого проекта с использованием паттерна MVVM: https://github.com/VoidVolker/LockScreen (тут уже интерфейс максимально простой). Несмотря на то, что само приложение на WPF, окно с картинкой пришлось делать на WinForms из-за костыльного DPI в современных виндах и, особенно в WPF. Аналогично пришлось поступать и в приложении со встроенным RDP клиентом - там всё ещё веселее в виде взаимного встраивания WPF и WinForms друг в друга и разделения на несколько проектов для создания работающих зависимостей от системных библиотек - спасибо LibMSTSC и мелкомягким за очень весёлые приключения.
    Ответ написан
  • Почему курсор мышки перестал совпадать с позицией на экране?

    VoidVolker
    @VoidVolker Куратор тега C#
    Dark side eye. А у нас печеньки! А у вас?
    Переключите масштабирование экрана в 100% и проверьте код - всё должно работать как было. В WPF накрутили свои фичи вокруг масштабирования и теперь даже банальное размещение окна в нужной позиции и нужного размера - это цирк с конями на велосипедах, жонглирующими хомяками-акробатами. К сожалению под рукой нет кода, но он легко гуглится по ключевым словам типа WPF DPI real cursor position / real window position. Там надо для каждого экрана получать DPI и использовать его для получения WPF координат или реальных координат на экране.
    Ответ написан
    2 комментария