• Как связать свойство Command Parameter у Context Menu со свойством Name у TextBox, к которому это меню привязано?

    FoggyFinder
    @FoggyFinder
    Вы столкнулись с широко известной проблемой привязки в ContextMenu, ToolTip из-за того что эти элементы не являются частью "визуального" дерева (visual tree).

    В таких случаях предлагается два стандартных решениях - использовать PlacementTarget и прокси-объект. Первое тут должно подойти идеально.

    Прежде чем показать код отмечу, что вместо использования свойства Name в качестве ключа TextBox лучше использовать свойство Tag.

    То есть вместо:

    <TextBox Name="Box_110" ...>

    <TextBox Tag="Box_110" ...>

    Это не принципиальное изменение, но в большинстве ответов для подобных случаев вы встретите использование именно свойство Tag.

    С учетом этого привязка для CommandParameter будет выглядеть вот так:

    <Setter Property="CommandParameter" Value="{Binding Path=PlacementTarget.Tag, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ContextMenu}}" />


    И немного оффтопа:

    В вашем обработчике ContextMenuClick вы используете постоянное смещение равное 10 и код по сути для каждого кейса одинаков. Вы могли бы сократить код, предварительно заменив подсказку в Tag убрав оттуда префикс "Box_" чтобы получилось что-то подобное:

    public void ContextMenuClick(object param)
    {
        if (int.TryParse(Convert.ToString(param), out int v))
        {
            StampDictionary.TextBoxes[v.ToString()].BoxValue = Name;
            StampDictionary.TextBoxes[(v + 10).ToString()].BoxValue = Signature;
        }
    }


    Если все ключи в словаре числовые, то еще проще будет заменит тип ключа на int.
    Ответ написан
    2 комментария
  • Как вытащить данные в формате json с помощью newtonsoft?

    FoggyFinder
    @FoggyFinder
    Ваш json - массив, а значит вместо JObject нужно использовать JArray.

    Дальше, если вы уверены что значение name для которого вы хотите узнать значение count существует и единственное используйте Single. Для извлечения значения определенного типа есть метод Value

    var test = JArray.Parse(json);
    var count = // count = 125
        test
        .Single(j => j.Value<string>("name") == "facebook")
        .Value<int>("count");


    Но если подобных поисков у вас будет много, то я все-же советую воспользоваться предложением VoidVolker и сгенерировать классы для более удобной работы. Например, преобразовать в словарь с ключами - name и значениями SomeItem.
    Ответ написан
    2 комментария
  • Какое новое ключевое слово в C# для иммутабельных классов?

    FoggyFinder
    @FoggyFinder
    То, о чем вы сейчас говорите, называется Records (записи), давно и успешное используемое в F#.
    Вопрос о том когда будет добавлена их поддержка в C# до сих пор открыт. Судя по всему в C# 8.0 не войдет. А дальше будет видно, так как слухи ходили еще со времен C# 6.0.

    В предложении фигурирует "with-expressions" которое позволит писать следующий код:

    e1 with { identifier = e2, ... }

    и будет равносильно

    e1.With(identifier2: e2, ...)

    Более подробную информацию вы можете узнать тут
    Ответ написан
    4 комментария
  • Как динамически менять значение TextBox, если Binding идет через Dictionary?

    FoggyFinder
    @FoggyFinder
    Чтобы сообщить представлению (View) об изменении значения конкретного свойства из VM нужно передать его название в виде параметра:

    OnPropertyChanged(nameof(TextBoxes));

    Непосредственно в самих свойствах вы можете увидеть что идет вызов без передачи параметров:

    OnPropertyChanged();

    Дело в том, что в типичной реализации имя свойства извлекается при помощи атрибута CallerMemberName:

    public event PropertyChangedEventHandler PropertyChanged;
    public void OnPropertyChanged([CallerMemberName]string prop = "")
    {
    // ...
    }


    Это не обязательно делать в set. У свойства может не быть открытого сеттера или не быть сеттера вообще. Или если свойство зависит от двух других - например, для автоматического отображения суммы значений, которые должен вводить пользователь.

    В вашем случае с TextBoxes вы не используете сеттер - его можно даже совсем убрать.
    Ответ написан
    2 комментария
  • Как получить значения DataGridView со всех форм?

    FoggyFinder
    @FoggyFinder
    Предположим, что нужно обрабатывать набор некоторых данных представляемых таблицей. У каждой таблицы есть заголовок, пользователь может добавлять произвольное число таблиц и редактировать данные в них. В качестве примера обработки возьмем простую сумму чисел.

    Начинаем с того, что описываем "модель" - все то, что относится к данным и их обработке. Тут всего два класса - SomeClass, который представляет собой данные из таблицы:

    public class SomeClass
    {
        public int M { get { return Data.GetLength(1); } }
        public int N { get { return Data.GetLength(0); } }
    
        public double[,] Data { get; }
    
        public SomeClass(double[,] data)
        {
            Data = new double[data.GetLength(0), data.GetLength(1)];
            Array.Copy(data, Data, data.Length);
        }
    
        public double Sum()
        {
            var s = 0.0;
            foreach (var x in Data)
                s += x;
            return s;
        }
    }


    и класс Item, который отвечает за таблицу. Тут все просто - таблица это сами данные и заголовок.

    public class Item
    {
        public string Title { get; }
        public SomeClass Data { get; }
    
        public Item(string title, SomeClass sc)
        {
            Title = title;
            if (sc != null)
                Data = new SomeClass(sc.Data);
        }
    
        public override string ToString() => Title;
    }


    Теперь представление для ячейки (одной таблицы). В таких случаях удобно создавать UserControl, назовем его ItemView

    Определим в нем два метода - Fill и Extract.

    Fill - отвечает за то чтобы отобразить указанный элемент.
    Extract - соберет информацию из элементов управления и вернет экземпляр класса Item.

    Таблицу можно описать в виде следующих элементов управления - двух TextBox для указания размерности (количество строк, столбцов) и DataGridView для заполнения значений.

    public void Fill(Item item)
    {
        label1.Text = item.Title;
        if (item.Data != null)
        {
            var n = item.Data.N;
            var m = item.Data.M;
            textBox1.Text = n.ToString();
            textBox2.Text = m.ToString();
    
            dataGridView1.ColumnCount = m;
            dataGridView1.RowCount = n;
    
            for (int i = 0; i < n; i++)
                for (int j = 0; j < m; j++)
                    dataGridView1[j, i].Value = item.Data.Data[i, j];
        }
        else
        {
            textBox1.Text = "";
            textBox2.Text = "";
    
            dataGridView1.ColumnCount = 0;
            dataGridView1.RowCount = 0;
        }
    }


    и реализация метода Extract:

    public Item Extract()
    {
        string title = label1.Text;
        if (string.IsNullOrWhiteSpace(title))
            return null;
    
        var n = dataGridView1.RowCount;
        var m = dataGridView1.ColumnCount;
    
        if (n == 0 || m == 0)
            return new Item(title, null);
    
        var data = new double[n, m];
    
        for (int i = 0; i < n; i++)
            for (int j = 0; j < m; j++)
                data[i, j] = Convert.ToDouble(dataGridView1[j, i].Value);
    
        return new Item(title, new SomeClass(data));
    }


    Код для задания размерности таблицы и генерации произвольных значений опускаю, чтобы излишне не раздувать ответ.

    Теперь практически все есть, можно переходить к созданию главной формы.
    Здесь понадобится ListBox для навигации между таблицами, панель, в которой будет размещаться UserControl, кнопка для расчетов и Label для вывода результатов.

    Чтобы связать модель с представлением воспользуемся классов BindingList:

    ItemView iview;
    BindingSource bs = new BindingSource()
    { DataSource = typeof(Item) };
    
    public Form1()
    {
        InitializeComponent();
        listBox1.DataSource = bs;
        bs.PositionChanged += PositionChanged;
    }


    PositionChanged - обработчик переключений между таблицами. Здесь нам нужно сохранять информацию в таблицу по старом индексу и отображать данные для новой.

    private void SaveCurrent()
    {
        var pr = iview.Extract();
        if (pr != null)
        {
            var old = bs.List.OfType<Item>().First(v => v.Title == pr.Title);
            var ind = bs.List.IndexOf(old);
            bs[ind] = pr;
        }
    }
    
    private void PositionChanged(object sender, EventArgs e)
    {
        if (bs.Current is Item item && bs.Count > 1)
        {
            SaveCurrent();
            iview.Fill(item);
        }
    }


    Здесь в методе SaveCurrent() мы последовательно выполняем следующие шаги:

    1. Извлекаем данные
    2. Ищем таблицу по указанному заголовку
    3. Ищем индекс в списке
    4. Обновляем таблицу

    и код для расчетов:

    SaveCurrent();
    var items = bs.OfType<Item>().Select(item => item.Data?.Sum() ?? -1);
    resLbl.Text = string.Join(";", items);


    Здесь тоже вызывается метод SaveCurrent() для принудительного сохранения при расчете.

    Итого, результат примерно следующий:

    5c975f2a21c91976114645.gif

    Код может быть не оптимальным, так как я в основном использую F# а не C# а также WPF а не WinForms, но главное тут суть подхода ;-)
    Ответ написан
    Комментировать
  • Как визуально разделить форму (окно) на части(блоки) в WindowsForms?

    FoggyFinder
    @FoggyFinder
    Используйте Layout-s, в вашем случае должен подойти TableLayoutPanel, который позволяет компоновать элементы управления в виде таблицы.

    Простой пример на русском языке можно найти тут:

    TableLayoutPanel
    Ответ написан
    Комментировать
  • Как предугадать рандом по тикам?

    FoggyFinder
    @FoggyFinder
    Если использовать конструктор по умолчанию класса Random, то в качестве зерна будет использоваться Environment.TickCount - время прошедшее с момента загрузки системы в миллисекундах.

    Для того, чтобы генерировать одну и ту-же последовательность есть отдельная перегрузка, которая принимает "зерно" - значение которое используется для выбора начального числа. Например, вы хотите использовать определенное время

    var ts = new TimeSpan(10, 10, 10);
    var rnd = new Random((int)ts.TotalMilliseconds);


    Таким образом будет генерироваться одна и та-же последовательность.

    for (int i = 0; i < 1; i++)
        Console.WriteLine("{0,4}", rnd.Next(50, 501)); // 265


    Еще можно заглянуть в исходники (Random.cs) и узнать реализацию чтобы "предсказание" было совсем точным :-)
    Ответ написан
    Комментировать
  • Почему консоль выводит первое ведённое число?

    FoggyFinder
    @FoggyFinder
    Как уже написали в других ответах, вам выводит вначале первое число, так как вы именно это и делаете сразу после считывания:

    x = int.Parse(Console.ReadLine());
    y = int.Parse(Console.ReadLine());
    //z = int.Parse(Console.ReadLine());
    Console.WriteLine(x);


    Но, подозреваю, что на самом деле вы спрашиваете о том, почему не выводит само число, а только букву:

    Console.WriteLine("X", x);

    Console.WriteLine ожидает увидеть в качестве первого параметра форматную строку:

    Console.WriteLine("X: {0}", x);

    или через интернирование строк:

    Console.WriteLine($"Y: {y}", y);

    На всякий случай приведу весь код с небольшими изменениями (убрал лишнее):

    int x = int.Parse(Console.ReadLine());
    int y = int.Parse(Console.ReadLine());
    if (x > y)
        Console.WriteLine("X: {0}", x);
    else
        Console.WriteLine($"Y: {y}", y);


    Дополнительно о форматировании строк можно прочитать в документации
    Ответ написан
    Комментировать
  • Как делать расчет по формулам?

    FoggyFinder
    @FoggyFinder
    Можно использовать готовые библиотеки.
    Например, MathNet.Symbolics

    Библиотека написана на F#, но вы можете использовать ее и в C# проекте:

    Math-NET-Symbolics-with-C-VB-NET-and-C-CLI

    Как видно из примера:

    using MathNet.Symbolics;
    using Expr = MathNet.Symbolics.SymbolicExpression;
    ...
    Expr.Parse("1/(a*b");  // выбросит исключение
    Expr.Parse("1/(a*b)").ToString(); // вернет строку "1/(a*b)"


    API достаточно удобное.

    С простыми функциями / формулами проблем быть не должно. Если возможностей будет не хватать или вы найдете баг - открывайте ишшью (на английском языке) или даже PR - мейнтейнер принимает их без проблем.

    А я в свою очередь, как один из контрибуторов, буду рад ответить на возможные вопросы или помочь с реализацией функционала.

    Есть и другие библиотеки, некоторые по возможностям превосходят MathNet.Symbolics, но так как я с ними не работал, то рекомендовать не могу.
    Ответ написан
    1 комментарий
  • Как сделать программу для заполнения данных в Word?

    FoggyFinder
    @FoggyFinder
    Не ясно почему были убрана метка "Программирование" из вопроса. Получается ответ в некотором роде будет оффтопом.

    Теперь по существу:

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

    Но если нужна именно программа, то я бы начал с составления ТЗ (технического задания), в котором было бы подробное описание требуемого функционала.

    Пока описание в вопросе довольно расплывчатое, но вот набросок который на скорую руку написал за пару часов на языке программирования F#:

    Примечание: Возможно F# не самый лучший выбор для данной задачи, но так как для своих персональных программ использую его, то и код привожу на нем.

    1. Определяются основные объекты (Студент, Преподаватель, Абитуриент) для которых в виде свойств перечисляются характеристики для заполнения:

    module Model
    
    type Student = {
        Name : string
        Surname : string
        LastName : string
        Phone : string
        Faculty : string
    }


    Отдельно, для удобства, представляем наши записи в виде размеченного объединения:

    [<RequireQualifiedAccess>]
    type AccountType = 
        | Student of Student
        | Enrollee of Enrollee
        | Teacher of Teacher


    Создаем модуль Defaults в котором будут находится значения по умолчанию для объектов (будет нужно для отображения):

    [<RequireQualifiedAccess>]
    module Defaults = 
        let student:Student = {
            Name = ""
            Surname = ""
            LastName = ""
            Phone = ""
            Faculty = ""
        }


    Следующий шаг - создание или редактирование / заполнение готового Word или Pdf шаблона данными.

    Есть несколько вариантов (библиотек) для работы и с тем и с другим форматом. Для Pdf есть очень известная библиотека:

    iTextSharp

    Есть и другие, как например,

    SharpLayout

    Документация в которой оставляет желать лучшего, но по крайней мере понятно что у нее нет проблем с отображением символов кириллицы.

    Простейший вывод в виде таблицы может выглядеть так:

    [<RequireQualifiedAccess>]
    module PdfReport
    
    open Model
    open PdfSharp.Drawing
    open SharpLayout
    
    let private defaultSettings = 
        PageSettings(
            TopMargin=Util.Cm(1.2),
            BottomMargin=Util.Cm(1.0),
            LeftMargin=Util.Cm(2.0),
            RightMargin=Util.Cm(1.0))
    
    let private createReportForTeacher teacher = 
        let document = Document()
        let section = document.Add(Section(defaultSettings))
        
        let font = 
            Font("Times New Roman", 10.0, XFontStyle.Regular, XPdfFontOptions.UnicodeDefault)
            |> Option
        
        section.Add(Paragraph().Add("Информация об преподователе", font.Value).Alignment(HorizontalAlign.Center.AsOption().ToNullable())) |> ignore
    
        let table = section.AddTable().Font font
        
        let c1 = table.AddColumn(Util.Px(600.0))
        let c2 = table.AddColumn(Util.Px(600.0))
        
        let r1 = table.AddRow()
        let r2 = table.AddRow()
        let r3 = table.AddRow()
        let r4 = table.AddRow()    
        let r5 = table.AddRow()
    
        r1.[c1].Add(Paragraph().Add("Имя:")) |> ignore
        r1.[c2].Add(Paragraph().Add(teacher.Name)) |> ignore
    
        r2.[c1].Add(Paragraph().Add("Фамилия:")) |> ignore
        r2.[c2].Add(Paragraph().Add(teacher.LastName)) |> ignore
    
        r3.[c1].Add(Paragraph().Add("Отчество:")) |> ignore
        r3.[c2].Add(Paragraph().Add(teacher.Surname)) |> ignore
    
        r4.[c1].Add(Paragraph().Add("Телефон:")) |> ignore
        r4.[c2].Add(Paragraph().Add(teacher.Phone)) |> ignore
    
        r5.[c1].Add(Paragraph().Add("Факультет:")) |> ignore
        r5.[c2].Add(Paragraph().Add(teacher.Faculty)) |> ignore
    
        document


    Теперь что касается отображения, мне удобнее использовать WPF, ссылка на руководство и библиотеку
    Gjallarhorn.Bindable.

    Для каждого типа создаем свой UserControl который будет отвечать за ввод данных.

    Каждое отображение определим в виде навигационного состояния:

    [<RequireQualifiedAccess>]
    type NavMessages = 
        | Student
        | Teacher
        | Enrollee


    работу с каждым типом вынесем в отдельные дочерние компоненты (StudentComponent, ...). Для каждого свойства можно определить собственное правило проверки корректности.

    let appComp =
        Component.create<AppModel, NavMessages, Messages> [
            <@ ctx.Model.Student @> |> Bind.comp (fun m -> m.Student) studentComp fst
            <@ ctx.Model.Enrollee @> |> Bind.comp (fun m -> m.Enrollee) enrolleeComp fst
            <@ ctx.Model.Teacher @> |> Bind.comp (fun m -> m.Teacher) teacherComp fst
                            
            <@ ctx.Model.Menu @> |> Bind.comp (fun m -> m.Menu) menuComponent fst
        
            <@ ctx.SendReport @> |> Bind.cmd
        ]


    Команда SendReport будет отвечать за созданием отчета и отправку его на почту. Кнопка будет активна только в том случае, если все поля заполнены без ошибок.

    Остается определить функцию обновления модели приложения:

    let upd (nav : Dispatcher<NavMessages>) message model = 
        match message with
        | Messages.SendReport ->
            let v, m = 
                match model.Menu.Current with
                | NavMessages.Enrollee -> 
                    AccountType.Enrollee model.Enrollee, { model with Enrollee = Defaults.enrollee }
                | NavMessages.Student -> 
                    AccountType.Student model.Student, { model with Student = Defaults.student }
                | NavMessages.Teacher -> 
                    AccountType.Teacher model.Teacher, { model with Teacher = Defaults.teacher }
            v
            |> PdfReport.createReport
            |> PdfReport.saveReport "test.pdf"
            |> PdfReport.sendReport
            m
        | Messages.SetCurrent current ->
            current |> nav.Dispatch
            { model with Menu = { model.Menu with Current = current }}
        | Messages.UpdateEnrollee msg ->
            { model with Enrollee = EnrolleeComponent.update model.Enrollee msg }
        | Messages.UpdateStudent msg ->
            { model with Student = StudentComponent.update model.Student msg }
        | Messages.UpdateTeacher msg ->
            { model with Teacher = TeacherComponent.update model.Teacher msg }
    
    open Gjallarhorn.Bindable.Framework
    
    let applicationCore nav =
        let navigation = Dispatcher<NavMessages>()
        Framework.application init (upd navigation) appComp nav
        |> Framework.withNavigation navigation


    Для работы с почтой вам нужно будет указать данные с которых вы хотите отправлять письмо. Как это сделать написано тут.

    Теперь, чтобы добавить новый тип нужно будет сделать следующее:

    1. Определить запись для нового объекта, описывающую его свойства.
    2. Создать функцию генерирующую отчет для этого типа.
    3. Создать компонент.
    4. Создать пользовательский элемент управления для отображения.
    5. Добавить его в общую модель программы.

    В итоге получилось следующее:

    5c7ece7614321212016044.gif

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

    В данном примере был записан такой pdf:

    5c7eceaae88cf238140201.jpeg

    Весь код не приводил, так как он довольно объемный, если такой вариант интересует, то могу выложить на гитхаб.

    Только учтите, что набросок можно сделать за пару часов, а довести до ума будет занимать намного больше времени.
    Ответ написан
    4 комментария
  • Как вывести оценки в программе С#?

    FoggyFinder
    @FoggyFinder
    Не совсем понятно что именно вызвало затруднения. Но давайте разбираться.

    1. У вас уже есть определение метода ToString для вашего объекта Student. Предлагаю его немного изменить - вместо передачи переменной, указывающей на запрос информации в подробном или сокращенном виде, разделим на два отдельных метода. ShortFormat , который вернет короткий вариант, тогда как переопределение стандартного ToString() для получения полных данных.

    public string ShortFormat()
    {
        return string.Format("{0,15} {1} {2}", Name, BirthDay.ToShortDateString(), GroupName);
    }
    
    public override string ToString()
    {
        StringBuilder sb = new StringBuilder(ShortFormat());
        sb.AppendLine("\nОценки:");
        foreach (var m in Marks)
            sb.AppendFormat("{0} - {1}\n", m.Key, m.Value);
        return sb.ToString();
    }


    2. Для определения есть ли у нашего студента задолженности воспользуемся методом ContainsValue :

    public bool HasDebt => Marks.ContainsValue(2);

    Теперь остается только правильно вызывать методы/свойства:

    switch (menu)
    {
        case 1:
            foreach (var student in students)
                Console.WriteLine(student);
            break;
        case 2:
            foreach (var student in students.Where(s => s.HasDebt))
                Console.WriteLine(student.ShortFormat());
            break;
    }


    Обратите внимание, что для фильтрации должников мы использовали Linq-метод Where.

    И в дополнение несколько комментариев:

    1. Выставлять наружу изменяемую коллекцию (в вашем случае Dictionary<_,_>) обычно не слишком хорошая идея, лучше добавить несколько вспомогательных методов/свойств, которые будут работать с приватным полем.

    2. В текущей реализации меню позволяет выбрать только одну опцию.
    Ответ написан
    Комментировать
  • Как выделить ячейку на ПКМ в DataGridView?

    FoggyFinder
    @FoggyFinder
    Один из вариантов:

    private void dataGridView1_CellMouseDown(object sender, DataGridViewCellMouseEventArgs e)
    {
        if (e.Button == MouseButtons.Right)
        {
            dataGridView1.ClearSelection();
            dataGridView1[e.ColumnIndex, e.RowIndex].Selected = true;
        }
    }
    Ответ написан
    Комментировать
  • Правильна ли логика копирования массива?

    FoggyFinder
    @FoggyFinder
    Если вам нужно сохранить порядок элементов, то просто воспользуйтесь готовым методом Array.Copy:

    Array.Copy(numbs, numbs2, numbs.Length);

    В противном случае, можно использовать циклы.

    for (int i = 0, z = 0; i < numbs2.GetLength(0); i++)
    {
        for (int j = 0; j < numbs2.GetLength(1); j++)
        {
            numbs2[i, j] = numbs[j, i];
            Console.Write(numbs2[i, j] + " ");
        }
    Console.WriteLine();
    }
    Ответ написан
  • Как правильно сделать функцию для повторяющихся действий?

    FoggyFinder
    @FoggyFinder
    Попробуйте рассматривать функцию в программировании как некоторый участок кода который выполняет определенное действие.

    Давайте разберем на примере вашего задания:

    Заданы три функции y1=x^3, y2=x^3+1, y3= 1/(1+x^2). Определить, являются ли эти функции четными или нечетными.


    Вас может смущать число "три" в формулировке, отбросьте его как не существенное, тогда будет проще понять как правильно поступить. Переформулируем, оставив только самую суть:

    Определить четность функций.


    Возьмем определение "четности":

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


    Так как функция может быть произвольная, то можно лишь говорить о свойствах на некотором интервале с заданным шагом.

    Определим тип функции в виде перечисления:

    public enum FuncType { Odd, Even, Unknown };

    Нам понадобиться функция которая будет определять тип функции для конкретной точки:

    Func<double, FuncType> isEven = v =>
    {
        var y1 = func(v);
        var y2 = func(-v);
    
        if (y1 == y2)
            return FuncType.Even;
        if (y1 == -y2)
            return FuncType.Odd;
    
        return FuncType.Unknown;
    };


    и функция для суммирования двух состояний:

    Func<FuncType, FuncType, FuncType> add = (v1, v2) =>
    {
        if (v1 == v2) return v2;
        return FuncType.Unknown;
    };


    теперь, чтобы не делать ненужные проверки, нужен способ вернуть результат сразу как только станет понятно, что функция не является ни четной ни нечетной:

    Для начала нужно определить "состояние" функции для первой точки (a) и, если, однозначного ответа нет, то можно возвращать результат - в дальнейших вычислениях нет необходимости:

    var funcType = isEven(a);
    if (funcType == FuncType.Unknown)
        return FuncType.Unknown;


    теперь, когда предварительная обработка сделана, можно писать цикл:

    for (double x = a + step; x <= b; x += step)
        {
            var funcTypeNext = isEven(x);
            funcType = add(funcType, funcTypeNext);
            if (funcType == FuncType.Unknown)
                return FuncType.Unknown;
         }


    и в итоге нужно вернуть funcType.

    Полностью функция выглядит так:

    public static FuncType IsEvenFunction(Func<double, double> func, double a, double b, double step)
    {
    
        Func<double, FuncType> isEven = v =>
        {
            var y1 = func(v);
            var y2 = func(-v);
    
            if (y1 == y2)
                return FuncType.Even;
            if (y1 == -y2)
                return FuncType.Odd;
    
            return FuncType.Unknown;
        };
    
        Func<FuncType, FuncType, FuncType> add = (v1, v2) =>
        {
            if (v1 == v2) return v2;
            return FuncType.Unknown;
        };
    
        var funcType = isEven(a);
        if (funcType == FuncType.Unknown)
            return FuncType.Unknown;
    
        for (double x = a + step; x <= b; x += step)
        {
            var funcTypeNext = isEven(x);
            funcType = add(funcType, funcTypeNext);
            if (funcType == FuncType.Unknown)
                return FuncType.Unknown;
        }
    
        return funcType;
    }


    Проверка:

    Func<double, double> fn1 = x => x * x * x;
    Func<double, double> fn2 = x => x * x * x + 1;
    Func<double, double> fn3 = x => 1 / (1 + x * x);
    
    Console.WriteLine("Fn1: {0}", IsEvenFunction(fn1, 1, 10, 0.01));
    Console.WriteLine("Fn2: {0}", IsEvenFunction(fn2, 1, 10, 0.01));
    Console.WriteLine("Fn3: {0}", IsEvenFunction(fn3, 1, 10, 0.01));


    Теперь что касается вывода как у вас примере, попробуйте добавить функцию .ToString() для форматирования перечисления. А также добавить описание для функции. Можно использовать кортеж - (описание, функция).

    Если возникнут вопросы - не стесняйтесь спрашивать, буду рад помочь.
    Ответ написан
    1 комментарий
  • Удаление элемента в List C#?

    FoggyFinder
    @FoggyFinder
    Можно использовать метод RemoveAll для удаления всех вхождений удовлетворяющих передаваемому предикату:

    public static void ClearPayment()
    {
        Console.Write("Введите код: ");
        int C = int.Parse(Console.ReadLine());
        if (payments.RemoveAll(p => p.Code == C) > 0)
            Console.WriteLine("Указанный платеж удален ");
        else
            Console.WriteLine("Платежа с таким кодом не существует");
    }


    RemoveAll вернет количество элементов, которые были удалены из списка.

    Еще один способ - использовать комбинацию методов из группы Find и Remove:

    FindIndex + RemoveAt

    или

    Find + Remove

    Отличие от Exists в том, что эти методы возвращают индекс (FindIndex) или сам элемент (Find), а не только проверяют существование подходящего элемента.
    Ответ написан
    Комментировать
  • Ошибка в использовании коллекций в c#?

    FoggyFinder
    @FoggyFinder
    Тут у вас сразу несколько ошибок:

    1. Метод new_list не принадлежит к какому-то определенному типу. Подозреваю, он должен находится в классе Program
    2. Для метода new_list не указан тип возвращаемого значения. Подозреваю, вы хотите чтобы метод возвращал Payment. В таком случае лучше переименовать на ReadPayment:

    public static Payment ReadPayment()
    {
        Console.Write("Введите марку бензина: ");
        int another_petrol = int.Parse(Console.ReadLine());
        Console.Write("Введите количество бензина в литрах: ");
        double another_count = double.Parse(Console.ReadLine());
        Console.Write("Введите номер колонки: ");
        byte another_column = byte.Parse(Console.ReadLine());
        Console.Write("Введите дату: ");
        byte another_code = byte.Parse(Console.ReadLine());
        Console.Write("Введите код: ");
        DateTime another_dt = DateTime.Parse(Console.ReadLine());
        return 
            new Payment(another_column, another_dt, another_petrol, another_count, another_code);
    }


    3. В методе Menu() вызов new_list() ничего не делает, полагаю, вы хотели добавить новый элемент в список:

    case '3':
        payments.Add(ReadPayment());
        break;


    На всякий случай приведу весь код:

    struct Payment
    {
        public int Petrol;
        public double Count;
        public DateTime Dt;
        public byte Column;
        public byte Code;
        public Payment(byte column, DateTime dt, int petrol, double count, byte code)
        {
            Column = column;
            Petrol = petrol;
            Count = count;
            Dt = dt;
            Code = code;
        }
    
        public String SString()
        {
            return String.Format("Колонка: {0} \n" +
                "Дата:  {1}.{2}.{3} {4}:{5}:{6} \n" +
                "Марка бензина: {7} \n" +
                "Количество: {8} \n" +
                "Код платежа: {9}" +
                "\n===============================", Column, Dt.Year, Dt.Month, Dt.Day, Dt.Hour, Dt.Minute, Dt.Second, Petrol, Count, Code);
        }
    }
    class Program
    {
        public static Payment ReadPayment()
        {
            Console.Write("Введите марку бензина: ");
            int another_petrol = int.Parse(Console.ReadLine());
            Console.Write("Введите количество бензина в литрах: ");
            double another_count = double.Parse(Console.ReadLine());
            Console.Write("Введите номер колонки: ");
            byte another_column = byte.Parse(Console.ReadLine());
            Console.Write("Введите дату: ");
            byte another_code = byte.Parse(Console.ReadLine());
            Console.Write("Введите код: ");
            DateTime another_dt = DateTime.Parse(Console.ReadLine());
            return
                new Payment(another_column, another_dt, another_petrol, another_count, another_code);
        }
        public static List<Payment> payments = new List<Payment>();
        public static void Menu()
        {
            Console.WriteLine("1. История платежей");
            Console.WriteLine("2. Редактировать историю платежей");
            Console.WriteLine("3. Добавить новый платеж");
            Console.WriteLine("4. Удалить платеж из списка");
            Console.WriteLine("5. Поиск платежа по коду");
            Console.WriteLine("6. Выход из программы");
            Console.Write("\n \nВведите номер пункта меню: ");
            char M = char.Parse(Console.ReadLine());
    
            switch (M)
            {
                case '1': break; // вывод списка платежей
                case '2': break;
                case '3':
                    payments.Add(ReadPayment());
                    break;
                case '4':
                    Console.WriteLine();
                    break;
                case '5': break;
                case '6': break;
            }
        }
        public static void Main(string[] args)
        {
            Menu();
            Payment np = new Payment(1, new DateTime(2000, 12, 13, 15, 12, 31), 92, 5.12, 001);
            payments.Add(np);
            payments.Add(new Payment(1, new DateTime(2012, 2, 12, 12, 42, 21), 92, 5.13, 001));
            foreach (Payment n in payments)
                Console.WriteLine(np.SString());
        }
    }


    Несколько комментариев:

    1. Вместо метода SString можно переопределять стандартный метод .ToString()
    2. Отклик на ввод пользователя лучше вынести из метода Menu, оставив там только саму печать на консоль.
    3. Структуру лучше делать неизменяемой в явном виде через readonly
    Ответ написан
    Комментировать
  • Как привязать данные таблицы к Combobox?

    FoggyFinder
    @FoggyFinder
    Все правильно, хотя, возможно, вам больше по душе придется стандартный ComboBox, а не
    DataGridComboBoxColumn:

    <DataGridTemplateColumn Header="Должность">
        <DataGridTemplateColumn.CellTemplate>
            <DataTemplate>
                <ComboBox
                     HorizontalContentAlignment="Center"
                     ItemsSource="{Binding DataContext.Titles, RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}"
                     SelectedItem="{Binding Title}" />
            </DataTemplate>
        </DataGridTemplateColumn.CellTemplate>
    </DataGridTemplateColumn>


    Будьте внимательны, в примере выше предполагается, что
    коллекция Titles находится на том же уровне (классе), что и коллекция Employee.
    Ответ написан
    Комментировать
  • Как создать свой дизайн интерфейса в WPF?

    FoggyFinder
    @FoggyFinder
    1. "Напрямую накидывать" вероятно, нельзя. Но возможность импорта все-таки присутствует:

    How to Import Photoshop Files into WPF

    Насколько такой способ рабочий сейчас - не знаю, не проверял.

    2. Blend for Visual Studio overview

    3. Metro UI особый стиль для приложений / сайтов. Для WPF есть очень известная библиотека MahApps.Metro.

    Теперь, что касается "стилизации" - WPF в плане настройки внешнего вида элементов управления и приложений в целом очень гибкий. Можно сделать практически все. Не буду даже пытаться раскрывать тему, материалов в сети очень много, но попробую дать направление для дальнейших поисков:

    Ключевые слова:

    • Style
    • DataTemplate
    • Trigger


    Для ознакомления материал из документации:

    Styling and Templating

    А для основательного разбора рекомендую следующую литературу:

    1. WPF: Windows Presentation Foundation в .NET 4.5 с ...

    2. WPF 4. Подробное руководство


    Сам я изучал WPF по книге Макдональда, материал изложен в доступной форме, но рассмотрение подробное, а не только основы.

    Есть и онлайн ресурсы:

    1. metanit: Руководство по WPF
    2. professorweb: WPF - Windows Presentation Foundation


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



    Первые две очень широко используются.

    И напоследок небольшое отступление:

    Больше практики, а если в чем-то не уверены - спрашивайте, здесь, на тостере или где-нибудь еще, не так важно.

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

    В принципе, можете попробовать совместить F# c WPF, возможности code-behind нам намного-намного меньше ;-), а значит проще будет пойти понять шаблоны MVVM или даже Elmish.
    Ответ написан
    Комментировать
  • Где лучше найти ментора для изучения Android?

    FoggyFinder
    @FoggyFinder
    Если вы готовы оплачивать консультации и/или наставничество, то на фрилансе должно быть достаточно желающих готовых помочь разобраться за ваши деньги.

    Что касается бесплатных вариантов, то FSSF (F# Software Foundation) в последнее время два раза в год проводит бесплатную программу наставничества F# Mentorship program. К сожалению, регистрация на зимнюю часть завершилась в начале этого месяца.

    Но, если вы еще не знакомы с F#, то вы можете потратить месяцы до открытия следующего набора на изучение этого потрясающего языка =)

    При подачи заявки вы указываете интересующее вас направление (основы, мобильная разработка, веб разработки и так далее) для лучшего распределения пар: наставник - обучающийся. Конечно, желающих быть ментором намного меньше, так что не расстраивайтесь если вам по каким-то причинам откажут. Отмечу, что даже в случае если вас не отобрали, вы все равно получите уведомление на почту.
    Ответ написан
    Комментировать
  • Почему чат-бот не читает пробелы в БД?

    FoggyFinder
    @FoggyFinder
    Проблема не в наличии пробельного символа в фразе вопроса, а в символе ?.

    В методе поиска соответствующего слова Ans вы удаляете из вопроса все вхождения следующих символов:

    ")(:^^=!?"

    Один из которых встречается в ключевой фразе "Как дела?".

    На данном этапе, вы можете делать аналогичное "удаление" символов для каждого вопроса из списка слов:

    if (q == Trim(baza[i], tr.ToCharArray()))

    Кроме этого оставлю несколько комментариев по коду:

    1. В методе Ans вы каждый раз считываете значения из файла по новой. На данном этапе лучше вынести получение данных в отдельный метод.
    2. Для хранения пары "ключ-значение" отлично подойдет структура данных [Словарь](https://docs.microsoft.com/en-us/dotnet/api/system...
    Ответ написан
    Комментировать