Ответы пользователя по тегу C#
  • С# используется больше для разработки игр или приложений?

    Casper-SC
    @Casper-SC
    Программист (.NET)
    WPF (Windows Presentation Foundation)
    UWP (Universal Windows Platform)
    ASP.NET Core (в общем и целом)
    ASP.NET Core Blazor
    ASP.NET Core MVC
    ML.NET
    Unity
    Я в этот список не включаю всякие Entity Framework Core и подобные технологии. Там ещё есть чем список пополнить.

    Достаточно посмотреть вакансии на разных сайтах. В основном, по моему субъективному мнению это ASP.NET и всякие другие консольные утилиты, которые работают в качестве серверов. Понятно, что все вышеперечисленные технологии используются тоже. На моей работе C# используется для UI приложения, для пары тройки серверов и для машинного обучения (в разных отделах) и много всего другого на разных языках.

    Писать приложения можно под все популярные ОС (Linux, MacOS, Windows)
    Ответ написан
    Комментировать
  • Вывести записи из БД циклом с фильтром по массиву?

    Casper-SC
    @Casper-SC
    Программист (.NET)
    Нужно сформировать одну строку вида "@record1, @record2" (параметризованные запросы), а потом уже передать в качестве параметров нужные значения.

    SELECT * FROM testimony WHERE Name IN(@record1, @record2)


    Примерно так (код не запускал, по быстрому набросал). Да, код можно написать лучше, это просто пример для понимания идеи. StringBuilder вместо string здесь приведёт к просадке производительности, малые строки быстрее так складывать:
    string sql = "SELECT * FROM testimony WHERE Name IN({0})";
    string parameters = "";
    string[] array = new string[] { "Запись 1", "Запись 2" };
    for (int i = 0; i < array.Length; i++)
    {
        parameters += "@record" + (i + 1) + (i < array.Length - 1 ? ", ": "");
    }
    
    using (SqlCommand cmd = new SqlCommand(string.Format(sql, parameters), this.connect))
    {
        // Добавить параметры
        for (int i = 0; i < array.Length; i++)
        {
            cmd.Parameters.AddWithValue("@record" + (i + 1), array[i]);
        }
    
        cmd.ExecuteNonQuery();
    }
    Ответ написан
    9 комментариев
  • Как взаимодействовать с элементом внутри DataTemplate?

    Casper-SC
    @Casper-SC
    Программист (.NET)
    Можно ещё сделать свой UserControl, в который поместить Ellipse и всю логику модификации его внешнего вида в XAML. Но нужно ли оно? Думаю, нет. Способов много это сделать.

    <DataGrid
        AutoGenerateColumns="False"
        ItemsSource="{Binding Income}">
        <DataGrid.Columns>
            <DataGridTemplateColumn
                CanUserReorder="False"
                CanUserResize="False"
                CanUserSort="False"
                IsReadOnly="True">
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate DataType="viewModels:IncomeViewModel">
                        <Ellipse Fill="{Binding IsModified, Converter={StaticResource BooleanToBrushConverter}}" />
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>
    </DataGrid>


    using GalaSoft.MvvmLight;
    
    namespace WpfApp.ViewModels
    {
        public class IncomeViewModel : ViewModelBase
        {
            private bool _isModified;
    
            public bool IsModified
            {
                get { return _isModified; }
                set { Set(ref _isModified, value); }
            }
        }
    }


    using System;
    using System.Globalization;
    using System.Windows.Data;
    using System.Windows.Media;
    
    namespace WpfApp.Converters
    {
        [ValueConversion(typeof(bool), typeof(SolidColorBrush))]
        public class BooleanToBrushConverter : IValueConverter
        {
            public SolidColorBrush TrueBrush { get; set; } = new SolidColorBrush(Colors.Tomato);
    
            public SolidColorBrush FalseBrush { get; set; } = new SolidColorBrush(Colors.CornflowerBlue);
    
            public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
            {
                return (bool)value ? TrueBrush : FalseBrush;
            }
    
            public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
            {
                return Binding.DoNothing;
            }
        }
    }
    Ответ написан
  • Как осуществить ввод и вывод данных WPF?

    Casper-SC
    @Casper-SC
    Программист (.NET)
    Обновлено:
    Ответ не совcем верный в том плане, что здесь нужно, как сейчас видится четыре DataGrid'a. Где у вас написано Зарплата, Сумма, Аренда, Сумма это всё данные одного DataGrid должны быть.
    5fc24d309b48a634078946.png
    *.csproj
    <Project Sdk="Microsoft.NET.Sdk.WindowsDesktop">
    
      <PropertyGroup>
        <OutputType>WinExe</OutputType>
        <TargetFramework>netcoreapp3.1</TargetFramework>
        <UseWPF>true</UseWPF>
      </PropertyGroup>
    
      <ItemGroup>
        <PackageReference Include="MvvmLightLibsStd10" Version="5.4.1.1" />
      </ItemGroup>
    
    </Project>


    <DataGrid
        Grid.Row="1"
        Grid.Column="1"
        AutoGenerateColumns="False"
        ItemsSource="{Binding Income}">
        <DataGrid.Columns>
            <DataGridTextColumn
                Width="67"
                Binding="{Binding Title}"
                Header="Title" />
            <DataGridTextColumn
                Width="67"
                Binding="{Binding Sum}"
                Header="Sum" />
        </DataGrid.Columns>
    </DataGrid>


    using System.Collections.ObjectModel;
    using GalaSoft.MvvmLight;
    
    namespace WpfApp1.ViewModels
    {
        public class MainViewModel : ViewModelBase
        {
            public ObservableCollection<IncomeViewModel> Income { get; }
    
            public MainViewModel()
            {
                Income = new ObservableCollection<IncomeViewModel>();
                // Просто для теста заполняем
                Income.Add(new IncomeViewModel { Title = "Зарплата", Sum = 100_000m });
            }
        }
    
        /// <summary>
        /// Модель представления одной строки в таблице Доход.
        /// </summary>
        public class IncomeViewModel : ViewModelBase
        {
            private string _title;
            private decimal _sum;
    
            public string Title
            {
                get { return _title; }
                set { Set(ref _title, value); }
            }
    
            public decimal Sum
            {
                get { return _sum; }
                set { Set(ref _sum, value); }
            }
        }
    }


    -------------

    У каждого DataGrid задайте свойства
    AutoGenerateColumns="False"
    ItemsSource="{Binding Elements}"


    Где Elements - это у каждого DataGrid своя коллекция данных во вью модели (Названия, понятное дело у них будут разные).

    Ещё можно задать в DataGrid'ах, где очень много данных (VirtualizingStackPanel):
    <DataGrid
        AutoGenerateColumns="False"
        ItemsSource="{Binding Elements}">
        <DataGrid.ItemsPanel>
            <ItemsPanelTemplate>
                <VirtualizingStackPanel
                    IsVirtualizing="True"
                    VirtualizationMode="Recycling" />
            </ItemsPanelTemplate>
        </DataGrid.ItemsPanel>
    </DataGrid>
    Ответ написан
    Комментировать
  • Как правильно реализовать информирование ViewModel'и по MVVM?

    Casper-SC
    @Casper-SC
    Программист (.NET)
    Читай комментарии в коде, в том числе зачем там lock. Вдруг ты будешь использовать такой поиск с отменой не в UI потоке (не именно этот код, а саму логику).

    Models/SearchAlgorithm.cs
    using System;
    using System.Threading;
    using System.Threading.Tasks;
    
    namespace EventsInModel.Models
    {
        public class SearchAlgorithm
        {
            public string CurrentFolder { get; private set; }
    
            public event EventHandler ProgressChanged;
    
            public async Task Search(CancellationToken cancellationToken)
            {
                for (int i = 0; i < 5; i++)
                {
                    await Task.Delay(1200, cancellationToken);
    
                    cancellationToken.ThrowIfCancellationRequested();
    
                    // Можно прогресс передавать и в качестве аргумента события,
                    // но в данном случае, вряд ли это оправдано. Обработав событие можно получить
                    // доступ к отправителю события и прочитать его свойства.
                    CurrentFolder = i.ToString();
                    ProgressChanged?.Invoke(this, EventArgs.Empty);
                }
            }
        }
    }


    ViewModels/MainViewModel.cs
    using System;
    using System.Threading;
    using System.Windows.Input;
    using EventsInModel.Models;
    using GalaSoft.MvvmLight;
    using GalaSoft.MvvmLight.Command;
    
    namespace EventsInModel.ViewModels
    {
        // ViewModelBase из библиотеки MvvmLight
        public class MainViewModel : ViewModelBase
        {
            //private readonly object _sync = new object();
            private readonly SearchAlgorithm _search;
    
            private string _currentFolder;
            // Логику с отменой можно вынести в отдельный класс, чтобы не писать простыню
            // с отменой в каждом таком месте с операцией, которая может быть отменена, а 
            // в UI приложениях такое сплошь и рядом.
            private volatile CancellationTokenSource _lastCancellationTokenSource;
    
            public string CurrentFolder
            {
                get { return _currentFolder; }
                private set { Set(ref _currentFolder, value); }
            }
    
            public ICommand SearchCommand { get; }
    
            public MainViewModel(SearchAlgorithm search)
            {
                _search = search;
                _search.ProgressChanged += OnSearchProgressChanged;
                SearchCommand = new RelayCommand(Search);
            }
    
            public override void Cleanup()
            {
                //lock (_sync)
                {
                    _lastCancellationTokenSource?.Cancel();
                }
    
                _search.ProgressChanged -= OnSearchProgressChanged;
                base.Cleanup();
            }
    
            /// <summary>
            /// Прерывает прошлый поиск и запускает новый.
            /// </summary>
            private async void Search()
            {
                CancellationTokenSource currentTokenSource;
                // В случае, если такой метод вызывать не из UI потока, то lock здесь нужен
                // Если использовать только из UI потока как здесь, то lock можно удалить.
                // Ещё бы я вынес логику в отдельный класс и использовал в других проектах в том числе.
                //lock (_sync)
                {
                    _lastCancellationTokenSource?.Cancel();
                    currentTokenSource = new CancellationTokenSource();
                    _lastCancellationTokenSource = currentTokenSource;
                }
    
                try
                {
                    await _search.Search(currentTokenSource.Token);
                }
                catch (OperationCanceledException)
                {
                    // Ignored.
                }
                finally
                {
                    //lock (_sync)
                    {
                        currentTokenSource.Dispose();
                        if (ReferenceEquals(_lastCancellationTokenSource, currentTokenSource))
                        {
                            _lastCancellationTokenSource = null;
                        }
                    }
                }
            }
    
            private void OnSearchProgressChanged(object sender, EventArgs e)
            {
                var search = (SearchAlgorithm)sender;
                CurrentFolder = search.CurrentFolder;
            }
        }
    }


    Затестил я по быстрому так. Это тебе не особо нужно:

    MainWindow.xaml.cs
    using System.Windows;
    using EventsInModel.Models;
    using EventsInModel.ViewModels;
    
    namespace EventsInModel
    {
        public partial class MainWindow : Window
        {
            private readonly MainViewModel _viewModel;
    
            public MainWindow()
            {
                InitializeComponent();
                _viewModel = new MainViewModel(new SearchAlgorithm());
                DataContext = _viewModel;
    
                Loaded += OnLoaded;
                Closing += OnClosing;
            }
    
            private void OnLoaded(object sender, RoutedEventArgs e)
            {
                _viewModel.SearchCommand.Execute(null);
                _viewModel.SearchCommand.Execute(null);
            }
    
            private void OnClosing(object sender, System.ComponentModel.CancelEventArgs e)
            {
                _viewModel.Cleanup();
            }
        }
    }


    Проект с зависимостями
    <Project Sdk="Microsoft.NET.Sdk.WindowsDesktop">
    
      <PropertyGroup>
        <OutputType>WinExe</OutputType>
        <TargetFramework>netcoreapp3.1</TargetFramework>
        <UseWPF>true</UseWPF>
      </PropertyGroup>
    
      <ItemGroup>
        <PackageReference Include="MvvmLightLibsStd10" Version="5.4.1.1" />
      </ItemGroup>
    
    </Project>
    Ответ написан
    1 комментарий
  • Как сделать цикл на основе ответа на Web запрос в C#?

    Casper-SC
    @Casper-SC
    Программист (.NET)
    Данный пример хорош тем, что ты можешь очень быстро создать ещё хоть 10 разных методов для обращения к API сервера. Часть кода была взята со справки майкрософта, частично модифицирована (где XML комментарии на английском).

    HttpClientExample.csproj
    <Project Sdk="Microsoft.NET.Sdk">
    
      <PropertyGroup>
        <OutputType>Exe</OutputType>
        <TargetFramework>netcoreapp3.1</TargetFramework>
      </PropertyGroup>
    
      <ItemGroup>
        <PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
      </ItemGroup>
    
    </Project>


    Точка входа в приложение и основной алгоритм по получению данных в цикле.
    Program.cs
    using System;
    using System.Threading;
    using System.Threading.Tasks;
    
    namespace HttpClientExample
    {
        class Program
        {
            // В качестве исключения я расположил в самом верху класса метод Main, 
            // обычно здесь должны быть поля класса, а все методы ниже.
            #region Entry point
    
            static async Task Main(string[] args)
            {
                var program = new Program();
                await program.Run(args);
            }
    
            #endregion
    
            private readonly SomeClient _client;
    
            public Program()
            {
                _client = new SomeClient("http://localhost:5000");
            }
    
            private async Task Run(string[] args)
            {
                bool success = false;
                do
                {
                    try
                    {
                        // CancellationToken пригодится в приложениях с UI, где нужно, например, 
                        // закрыть окно или уйти со страницы не дожидаясь, пока запрос отработает. 
                        // Здесь заранее это заложено, можно и не использовать, если приложение консольное.
                        string data = await _client.GetData(CancellationToken.None);
                        success = true;
    
                        Console.WriteLine(data);
                    }
                    catch (ApiException ex)
                    {
                        // Одна реакция
                        Console.WriteLine(ex);
                        Console.WriteLine();
                    }
                    catch (Exception ex)
                    {
                        // Другая реакция
                        Console.WriteLine(ex);
                        Console.WriteLine();
                    }
    
                    await Task.Delay(150);
                } while (!success);
    
                _client.Dispose();
            }
        }
    }


    SomeClient.cs
    using System;
    using System.Collections.Generic;
    using System.Net;
    using System.Net.Http;
    using System.Text;
    using System.Threading;
    using System.Threading.Tasks;
    using Newtonsoft.Json;
    
    namespace HttpClientExample
    {
        public class SomeClient : IDisposable
        {
            private const string GET_TEXT_PART = "/api/system/get-text";
            private const string GET_USER_PART = "/api/system/get-user";
    
            private HttpClient _httpClient;
    
            public Dictionary<string, string> DefaultHeaders { get; }
    
            public SomeClient(string baseAddress)
            {
                var httpHandler = new HttpClientHandler
                {
                    AutomaticDecompression = DecompressionMethods.Deflate | DecompressionMethods.GZip
                };
    
                _httpClient = new HttpClient(httpHandler)
                {
                    BaseAddress = new Uri(baseAddress)
                };
    
                DefaultHeaders = new Dictionary<string, string>
                {
                    ["Accept"] = "*/*",
                    ["Accept-Encoding"] = "gzip, deflate",
                    ["Cache-Control"] = "no-cache",
                    ["Connection"] = "keep-alive",
                };
            }
    
            public void Dispose()
            {
                if (_httpClient != null)
                {
                    _httpClient.Dispose();
                    _httpClient = null;
                    GC.SuppressFinalize(this);
                }
            }
    
            public async Task<string> GetData(CancellationToken cancellationToken)
            {
                string text = await InvokeText(HttpMethod.Get, GET_TEXT_PART, cancellationToken);
                // Возможно, что-то залогировал.
                return text;
            }
    
            public async Task<User> GetUser(CancellationToken cancellationToken)
            {
                var user = await InvokeJson<User>(HttpMethod.Get, GET_USER_PART, cancellationToken);
                // Возможно, что-то залогировал.
                return user;
            }
    
            /// <summary>
            /// Sets the request.
            /// </summary>
            /// <param name="request">The request.</param>
            /// <param name="requestContent">Content of the request.</param>
            private void SetRequest(HttpRequestMessage request, object requestContent)
            {
                foreach (var header in DefaultHeaders)
                {
                    request.Headers.Add(header.Key, header.Value);
                }
    
                if (requestContent != null)
                {
                    request.Content = new StringContent(JsonConvert.SerializeObject(requestContent),
                        Encoding.UTF8,
                        Constants.HttpMimeTypes.JsonContentType);
                }
            }
    
            /// <summary>
            /// Invokes the specified HTTP method.
            /// </summary>
            /// <param name="httpMethod">The HTTP method.</param>
            /// <param name="relativeUrl">The relative URL.</param>
            /// <param name="cancellationToken">Cancellation token.</param>
            /// <param name="requestContent">Content of the request.</param>
            /// <returns>instance of the type T</returns>
            /// <exception cref="ApiException"></exception>
            private async Task<string> InvokeText(HttpMethod httpMethod, string relativeUrl, CancellationToken cancellationToken, object requestContent = null)
            {
                using (var request = new HttpRequestMessage(httpMethod, relativeUrl))
                {
                    SetRequest(request, requestContent);
    
                    using (HttpResponseMessage response = await _httpClient.SendAsync(request, HttpCompletionOption.ResponseContentRead, cancellationToken))
                    {
                        string responseText = await response.Content.ReadAsStringAsync();
                        if (response.IsSuccessStatusCode)
                        {
                            return responseText;
                        }
    
                        throw new ApiException(response.StatusCode, responseText);
                    }
                }
            }
    
            /// <summary>
            /// Invokes the specified HTTP method.
            /// </summary>
            /// <typeparam name="T"></typeparam>
            /// <param name="httpMethod">The HTTP method.</param>
            /// <param name="relativeUrl">The relative URL.</param>
            /// <param name="cancellationToken">Cancellation token.</param>
            /// <param name="requestContent">Content of the request.</param>
            /// <returns>instance of the type T</returns>
            /// <exception cref="ApiException"></exception>
            private async Task<T> InvokeJson<T>(HttpMethod httpMethod, string relativeUrl, CancellationToken cancellationToken, object requestContent = null)
            {
                using (var request = new HttpRequestMessage(httpMethod, relativeUrl))
                {
                    SetRequest(request, requestContent);
    
                    using (HttpResponseMessage response = await _httpClient.SendAsync(request, HttpCompletionOption.ResponseContentRead, cancellationToken))
                    {
                        string responseText = await response.Content.ReadAsStringAsync();
                        if (response.IsSuccessStatusCode)
                        {
                            var resource = JsonConvert.DeserializeObject<T>(responseText);
                            return resource;
                        }
    
                        throw new ApiException(response.StatusCode, responseText);
                    }
                }
            }
    
            private static class Constants
            {
                public static class HttpMimeTypes
                {
                    /// <summary>
                    /// The json content type
                    /// </summary>
                    public const string JsonContentType = "application/json";
                }
            }
        }
    }


    Этот класс используется просто для примера, как преобразовать JSON, полученный от сервера в экземпляр класса
    User.cs
    using Newtonsoft.Json;
    
    namespace HttpClientExample
    {
        public class User
        {
            [JsonProperty("id", Required = Required.Always)]
            public long Id { get; set; }
    
            [JsonProperty("name", Required = Required.Always)]
            public string Name { get; set; }
        }
    }


    async await, чтобы было примепрное понимание, что происходит.
    Скриншот сделан с видео: https://youtu.be/lh8cT6qI-nA?t=1123
    5fb13cbe569ab013358287.jpeg
    Ответ написан
    Комментировать
  • С помощью чего отправлять почту в Asp.Net Core 3.1?

    Casper-SC
    @Casper-SC
    Программист (.NET)
    Есть такой вариант: How to send emails in ASP.NET Core

    www.mimekit.net

    В описании по ссылке написано:
    Run Anywhere
    MimeKit and MailKit support Windows, Linux, Mac, iOS, Android, Windows Phone and more!
    Ответ написан
    2 комментария
  • С# вместо Python - стоит ли усложнять?

    Casper-SC
    @Casper-SC
    Программист (.NET)
    Я пишу на C# и писал немного на Python. Мне второй понравился тем, что там можно быстро писать всякие небольшие программы. Быстро что-то набросать. Есть много разных книг по машинному обучению. Ну и как новое после C# было интересно учить. С одной стороны динамическая типизация - это удобно, с другой можно наворотить страшные вещи. Я за строгую типизацию. В таких проектах легче разбираться, легче поддерживать, рефакторить и т.д. Я за C#. Бэкенд на C# тоже можно писать весьма приличный. На C# можно писать под Linux, MacOS и Windows. Скорость разработки упадёт или нет это ещё спорный вопрос, смотря как код писать, если на Python чисто копипастить - за то быстро, то я бы посмотрел на выражение лица того, кто этот проект будет поддерживать. Я хотел сказать, что на любом языке можно написать плохо и динамическая типизация не спасёт от того, что человек будет зависать на частях проекта, что-то менять и ломать другую часть проекта. Со строгой типизацией и средствами рефакторинга вроде JetBrains ReSharper (в JetBrains Rider это сразу встроено) в C# проект не поломаешь так легко, а если поломаешь, то он просто не соберётся, пока не поправишь все ошибки, ведь типизация статическая и сразу будут видны все нестыковки. Вообще странное утверждение, что под Windows хорош C#. Он хорош под всё. На Python, какое-то время назад было больше библиотек для науки, для машинного обучения и т.д. сейчас уже много чего для этих дел есть и у C# (там, кстати, есть и сравнение с Python библиотеками - раздел High performance and accuracy). Ну и сам язык развивается, постоянно появляются новые крутые фишки в нём. Так же есть ещё и F#, почти Python, но не так популярен и распространён.

    Среды разработки:
    * Microsoft Visual Studio - под Windows
    * JetBrains Rider - под всё
    Ответ написан
    7 комментариев
  • С# Taks и Invoke почему то блокируется форма?

    Casper-SC
    @Casper-SC
    Программист (.NET)
    Посмотри как я реализовал класс Analyzer, напиши свой алгоритм по такому же принципу. Внимательно прочитай комментарии в коде класса. Почитай про события в C#. Напиши отдельный класс с алгоритмом, который генерирует события, а уже в форме подпишись на события и обновляй UI. Сообщения из алгоритма отправляй через контекст синхронизации, в алгоритме не дожидайся завершения работы обработчика события (метод Post у контекста синхронизации потоков). Не пиши весь код в методах обработчиках событий форм (окон).

    В классе Analyzer
    await Task.Delay(250);
    просто для имитации долгой работы.

    Код ниже слегка отличается от кода по ссылке.
    using System;
    using System.Threading;
    using System.Threading.Tasks;
    
    namespace ProgressBarExample
    {
        internal class Analyzer
        {
            private readonly SynchronizationContext _synchronizationContext;
    
            public Analyzer()
            {
                // Если экземпляр класса будет создан в UI потоке,
                // то здесь будет контекст синхронизации UI потока, иначе пула потоков
                _synchronizationContext = SynchronizationContext.Current ?? new SynchronizationContext();
            }
    
            public event EventHandler<AnalyzerEventArgs> ProgressChanged;
    
            public Task<Data> DoWork()
            {
                return Task.Run(async () =>
                {
                    for (int i = 0; i < 100; i++)
                    {
                        // Имитация долгой работы
                        await Task.Delay(250);
                        // Здесь ты можешь так же как в своём коде вызывать OnProgressChanged
                        // раз в несколько миллисекунд. В форме в UI потоке без Invoke обрабатывать 
                        // событие, выводя те данные, которые ты поместишь в AnalyzerEventArgs
                        OnProgressChanged(new AnalyzerEventArgs("line " + (i + 1), 100));
                    }
                    return new Data() { Text = "Данные " };
                });
            }
    
            private void OnProgressChanged(AnalyzerEventArgs args)
            {
                // Перенаправляем выполнение в UI поток не ожидая пока отработает метод обработчик события.
                _synchronizationContext.Post(state =>
                {
                    ProgressChanged?.Invoke(this, (AnalyzerEventArgs)state);
                }, args); // args передаётся в переменную state (грубо говоря)
            }
        }
    }


    namespace ProgressBarExample
    {
        public class AnalyzerEventArgs
        {
            public int MaxLines { get; }
    
            public string CurrentLine { get; }
    
            public AnalyzerEventArgs(string currentLine, int maxLines)
            {
                CurrentLine = currentLine;
                MaxLines = maxLines;
            }
        }
    }


    namespace ProgressBarExample
    {
        public class Data
        {
            public string Text { get; set; }
        }
    }


    По ссылке полный код WPF приложения (не важно какой проект, в Windows Forms всё так же будет работать).
    Как сделать, чтобы ProgressBar работал во время нагрузки на приложение?
    Ответ написан
    1 комментарий
  • Как в .NET Core под Linux парсить Word/Excel?

    Casper-SC
    @Casper-SC
    Программист (.NET)
    Для Excel есть ClosedXML.

    Так же есть NPOI. Сам не использовал, но, похоже, он годится и для Excel и для Word.
    Ответ написан
    Комментировать
  • C# или Python под Linux и Windows?

    Casper-SC
    @Casper-SC
    Программист (.NET)
    C# + AvaloniaUI (почти один в один как WPF), если нужен UI под Linux, Windows и macOS.
    Если в Windows 10 не установлен .NET Core или .NET Framework, то Windows сама предлагает всё установить, при первом запуске приложения. Нет с этим проблем. Ничего не нужно искать, читать, просто соглашаешься и всё само ставится. Это если без инсталлятора.
    Ответ написан
    Комментировать
  • Что не так в коде?

    Casper-SC
    @Casper-SC
    Программист (.NET)
    1. Стиль именования какой-то странный и смешанный. Можно глянуть здесь, как нужно оформлять код (не навязываю, но это именно тот стиль, в котором написан .NET Core и прочий дотнет):
    Как можно проверить,что цифры числа расположены в возрастающем порядке или в убывающем?
    Как осуществить переход между страницами в Windows Presentation Foundation? (только закомментированный оставлять не нужно, здесь для примера)
    Как сделать считывание с input и вывод в output на C#?
    Не используй русские символы, транслит, и префиксы. Не оставляй гигантские пробелы между методами.

    2. async void processing. Здесь нужно возвращать Task и он должен ожидаться в месте вызова, даже если на этом заканчивается работа метода. Если этот код вызывается по клику, то что будет если кликнуть 2 или 10 раз?

    3. Метод processing не меняет значения текстовых полей, в коде идёт присвоение значений параметрам, но эти значения не попадут в текстовые поля в окне.

    4. Магические переменные i и v. Нужно давать понятные названия.

    int i = CarNumber.Length; // Я уже переименовал и свойства
    int v = CarMark.Length;


    5. Здесь вообще Task не нужен на такой задаче, если это примерно то кол-во данных, которое будет обрабатываться.

    6. Если бы даже код был написан так, что значения бы присваивались текстовым полям в окне, то приложение бы крашилось из-за обращения к UI элементам из не UI потока.

    7. Впечатление, что автор кода думает, что может быть ошибка в коде и переменная станет меньше нуля. Зачем здесь <=, если должно быть ==?
    if (i <= 0)
    {
        dataProperty = $"Данной машины не найдено на парковке";
        dataPlace = $"Повторите попытку";
    }


    8. Здесь не нужен знак $.
    $"Данной машины не найдено на парковке";

    9. В принципе класс-парсер построен неправильно.
    Ответ написан
    Комментировать
  • Как проверить начинается ли строка с пробела c#?

    Casper-SC
    @Casper-SC
    Программист (.NET)
    string text = "   ssd";
    if (text.StartsWith(" "))
    {
    }
    Ответ написан
    Комментировать
  • Как осуществить переход между страницами в Windows Presentation Foundation?

    Casper-SC
    @Casper-SC
    Программист (.NET)
    Microsoft Docs: How to: Navigate to a Page
    Microsoft Docs: NavigationWindow Class
    Хабр: WPF Navigation: Используем связку Page + Frame

    namespace PageNavigation.Services
    {
        public interface INavigationService
        {
            void NavigateToPage1();
    
            void NavigateToPage2();
        }
    }


    using System.Windows.Controls;
    using PageNavigation.Pages;
    
    namespace PageNavigation.Services
    {
        public class NavigationService : INavigationService
        {
            private readonly Frame _frame;
    
            public NavigationService(Frame frame)
            {
                _frame = frame;
            }
    
            public void NavigateToPage1()
            {
                _frame.Navigate(new Page1());
            }
    
            public void NavigateToPage2()
            {
                _frame.Navigate(new Page2());
            }
        }
    }


    Такой Ioc:
    using System.Windows.Controls;
    
    namespace PageNavigation.Services
    {
        public static class Ioc
        {
            public static INavigationService NavigationService { get; private set; }
    
            public static void Init(Frame frame)
            {
                NavigationService = new NavigationService(frame);
            }
        }
    }


    Или такой Ioc:
    https://autofac.org/
    using System.Windows.Controls;
    using Autofac;
    
    namespace PageNavigation.Services
    {
        public static class Ioc
        {
            private static IContainer _container;
    
            public static INavigationService NavigationService
            {
                get { return _container.Resolve<INavigationService>(); }
            }
    
            //public static MainViewModel MainViewModel
            //{
            //    get { return _container.Resolve<MainViewModel>(); }
            //}
    
            public static void Init(Frame frame)
            {
                var builder = new ContainerBuilder();
                
                builder.RegisterType<NavigationService>()
                    .As<INavigationService>()
                    .SingleInstance()
                    .WithParameter(new TypedParameter(typeof(Frame), frame));
    
                //builder.RegisterType<MainViewModel>()
                //    .SingleInstance();
    
                _container = builder.Build();
            }
        }
    }


    Главное окно XAML
    <Window
        x:Class="PageNavigation.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"
        Title="MainWindow"
        Width="525"
        Height="350"
        Loaded="OnLoaded"
        WindowStartupLocation="CenterScreen"
        mc:Ignorable="d">
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="266*" />
                <RowDefinition Height="Auto" />
            </Grid.RowDefinitions>
    
            <Frame x:Name="_frame" />
    
            <StackPanel
                Grid.Row="1"
                Margin="8,0,0,6"
                Orientation="Horizontal">
    
                <Button
                    MinWidth="75"
                    MinHeight="29"
                    HorizontalAlignment="Left"
                    VerticalAlignment="Top"
                    Click="OnNavigateToPage1ButtonClick"
                    Content="Page1" />
    
                <Button
                    MinWidth="75"
                    MinHeight="29"
                    Margin="8,0,0,0"
                    HorizontalAlignment="Left"
                    VerticalAlignment="Top"
                    Click="OnNavigateToPage2ButtonClick"
                    Content="Page2" />
            </StackPanel>
        </Grid>
    </Window>


    Главное окно C#
    using System.Windows;
    using PageNavigation.Services;
    
    namespace PageNavigation
    {
        public partial class MainWindow : Window
        {
            public MainWindow()
            {
                InitializeComponent();
            }
    
            private void OnLoaded(object sender, RoutedEventArgs e)
            {
                Ioc.Init(_frame);
            }
    
            private void OnNavigateToPage1ButtonClick(object sender, RoutedEventArgs e)
            {
                Ioc.NavigationService.NavigateToPage1();
            }
    
            private void OnNavigateToPage2ButtonClick(object sender, RoutedEventArgs e)
            {
                Ioc.NavigationService.NavigateToPage2();
            }
        }
    }


    Страница 1 XAML
    <Page
        x:Class="PageNavigation.Pages.Page1"
        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"
        Title="Page1"
        d:DesignHeight="300"
        d:DesignWidth="300"
        mc:Ignorable="d">
    
        <Grid>
    
            <TextBlock Margin="5">
                Это Page 1
            </TextBlock>
    
            <Button
                Padding="12,3,12,3"
                HorizontalAlignment="Center"
                VerticalAlignment="Center"
                Click="OnNavigateToAnotherPageButtonClick"
                Content="Перейти на Page 2" />
        </Grid>
    </Page>


    Страница 1 C#
    using System.Windows.Controls;
    using PageNavigation.Services;
    
    namespace PageNavigation.Pages
    {
        public partial class Page1 : Page
        {
            public Page1()
            {
                InitializeComponent();
            }
    
            private void OnNavigateToAnotherPageButtonClick(object sender, System.Windows.RoutedEventArgs e)
            {
                Ioc.NavigationService.NavigateToPage2();
            }
        }
    }


    Страница 2 XAML
    <Page
        x:Class="PageNavigation.Pages.Page2"
        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"
        Title="Page2"
        d:DesignHeight="300"
        d:DesignWidth="300"
        mc:Ignorable="d">
    
        <Grid>
    
            <TextBlock Margin="5">
                Это Page 2
            </TextBlock>
    
            <Button
                Padding="12,3,12,3"
                HorizontalAlignment="Center"
                VerticalAlignment="Center"
                Click="OnNavigateToAnotherPageButtonClick"
                Content="Перейти на Page 1" />
        </Grid>
    </Page>


    Страница 2 C#
    using System.Windows;
    using System.Windows.Controls;
    using PageNavigation.Services;
    
    namespace PageNavigation.Pages
    {
        public partial class Page2 : Page
        {
            public Page2()
            {
                InitializeComponent();
            }
    
            private void OnNavigateToAnotherPageButtonClick(object sender, RoutedEventArgs e)
            {
                Ioc.NavigationService.NavigateToPage1();
            }
        }
    }
    Ответ написан
    1 комментарий
  • Дайте совет где учить Unity и C#?

    Casper-SC
    @Casper-SC
    Программист (.NET)
    Лучше книг нет ничего. Это в первую очередь, а в дополнение уже можно использовать и другие ресурсы, вроде видеокурсов. В книгах больше всего полезной и важной информации.

    Книги C#:
    Язык программирования C# 7 и платформы .NET и .NET Core | Троелсен Эндрю, Джепикс Филипп

    Видеокурсы по C#:
    Поиск курсов по C# на Stepik
    Нашёл такой видеокурс
    И ещё один, более старый, но я его смотрел и помню, что он качественный.
    Смотреть исходники .NET Core (строка поиска слева сверху)

    Какие посоветуете книги по C# и смежным технологиям для начинающего?

    Книга по Unity:
    Unity в действии | Хокинг Джозеф

    Видеокурсы по Unity:
    Поиск курсов по Unity на Udemy
    Ответ написан
    Комментировать
  • Как сделать считывание с input и вывод в output на C#?

    Casper-SC
    @Casper-SC
    Программист (.NET)
    using System;
    using System.IO;
    
    namespace InputOutputExample
    {
        class Program
        {
            static void Main(string[] args)
            {
                string inputFile = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "input.txt");
                string outputFile = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "output.txt");
    
                using var input = new StreamReader(File.OpenRead(inputFile));
                Console.SetIn(input);
                
                using var output = new StreamWriter(File.OpenWrite(outputFile));
                Console.SetOut(output);
    
                string line = null;
                while ((line = Console.ReadLine()) != null)
                {
                    Console.WriteLine(line);
                }
            }
        }
    }


    5f539743c3eec503656175.png

    5f53974b97194787313157.png
    Ответ написан
    Комментировать
  • Какие вы знаете хорошие курсы по c# с нуля?

    Casper-SC
    @Casper-SC
    Программист (.NET)
    Книги нужно читать. Курсы нужно смотреть для закрепления уже после книг.
    Вот курс, где я многое узнал уже после книги, так как это было первое серьёзное изучение языка и я много чего не увидел или не понял из книги.
    Курс C# Base

    Главная книга:
    Язык программирования C# 7 и платформы .NET и .NET Core | Джепикс Филипп, Троелсен Эндрю

    Разработка приложений ASP.NET Core

    Книги (там нет книг по WPF и упоминания UWP):
    Какие посоветуете книги по C# и смежным технологиям для начинающего?

    Одновременно нужно во время изучения языка создать решение (Solution) и в нём создать проекты по каждой теме или нескольким темам, что позволит в будущем возвращаться к старому материалу, чтобы быстро вспомнить.

    Грубый пример проектов в решении:
    Изучение C# (.sln)
    1. Переменные, циклы (.csproj)
    2. Классы (.csproj)
    3. Наследование (.csproj)
    4. Делегаты и события (.csproj)

    Все проекты нужно именовать по-английски в стиле CamelCase. Выше просто пример, чтобы было понятно.
    Ответ написан
    Комментировать
  • Какова приемлемая скорость модульного теста?

    Casper-SC
    @Casper-SC
    Программист (.NET)
    Тесты выполняются так же как и любой другой код. Стоит искать причину в коде. Хотя из-за отсутствии инофрмации о том, что делает тест и как написан код - это просто 50/50. Я либо угадал, либо нет (в чём искать причину).
    Ответ написан
  • Как компилятор понимает, что первую функцию, которую нужно вызвать, будет именно Main()?

    Casper-SC
    @Casper-SC
    Программист (.NET)
    В книге CLR via C# - Программирование на платформе Microsoft.NET Framework 4.5 на языке C#. 4-е издание на странице 37 в главе Исполнение кода сборки написано:
    Далее основной поток вызывает определенный в библиотеке MSCorEE.dll метод, который инициализирует CLR, загружает сборку EXE, а затем вызывает ее метод Main, в котором содержится точка входа. На этом процедура запуска управляемого приложения считается завершенной.


    Так же написано в документации Microsoft, что вызывается именно метод Main, если в качестве параметра компилятора -main не передать название другого метода.

    Документация Microsoft:
    Main() и аргументы командной строки
    Запуск приложения
    Ответ написан
    22 комментария