• Как определить что элемент в рабочей области?

    lam0x86
    @lam0x86
    Вообще, в WPF с виртуализацией данных всё довольно печально. Из-за её отсутствия и расплодилось такое количество сторонних гридов. Но тем не менее, можно подписаться на события ItemContainerGenerator-а, который отвечает за визуальную виртуализацию, и подгружать данные во время появления контейнера строк на экране.
    Ответ написан
    Комментировать
  • Как восстановить xaml из baml?

    lam0x86
    @lam0x86
    На сколько я понял из приведенного кода, нужно писать так:
    <Window x:Class="ссылка на класс Login" ...>
    ...
    </Window>
    Ответ написан
  • Как правильно информировать о процессе выполнения задачи?

    lam0x86
    @lam0x86
    Пробовал через класс Progress, но тут мне не понравилось плодить большое кол во классов через
    Progress.Report(new MyReport{...});

    Ничего страшного в этом нет - эти объекты на самом деле тут же умирают, не покидая первого поколения GC.
    Тут другой вопрос более важен: класс Progress устроен так, что маршаллит все репорты в SynchronizationContext, в котором он был создан. В случае с WinForms - это контекст UI-потока. Если ваш Task слишком часто будет вызывать метод Report, это может негативно сказаться на UI-потоке, т.к. он будет забит репортами, каждый из которых он должен обработать. Более того, поскольку маршаллинг в классе Progress асинхронный, есть вероятность, что задача будет выполнена до того, как на UI-потоке обработаются все репорты. Получется запаздывание прогресс-бара от реального прогресса (и вот тут как раз возникает вероятность перехода репортов в Gen1 и Gen2).

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

    public interface IProgressInfo
        {
            bool IsCompleted { get; }
        }
    
        public class ProgressInfo : IProgressInfo
        {
            public ProgressInfo(double completedPercentage, string progressStatusText)
            {
                CompletedPercentage = completedPercentage;
                ProgressStatusText = progressStatusText;
            }
    
            public double CompletedPercentage { get; private set; }
    
            public string ProgressStatusText { get; private set; }
    
            public bool IsCompleted
            {
                get { return CompletedPercentage >= 1; }
            }
        }
    
        public class Progress<T> : IProgress<T> where T : class, IProgressInfo
        {
            private T _previousProgressInfo;
            private volatile T _progressInfo;
            private readonly Action<T> _updateProgressAction;
            private readonly Timer _timer;
            private readonly SynchronizationContext _synchronizationContext;
    
            public Progress(TimeSpan pollingInterval, Action<T> updateProgressAction)
            {
                _synchronizationContext = SynchronizationContext.Current ?? new SynchronizationContext();
                _updateProgressAction = updateProgressAction;
                _timer = new Timer(TimerCallback, null, pollingInterval, pollingInterval);
            }
    
            private void TimerCallback(object state)
            {
                ProcessUpdate();
            }
    
            private void ProcessUpdate()
            {
                var progressInfo = _progressInfo;
                if (_previousProgressInfo != progressInfo)
                {
                    _synchronizationContext.Send(state => _updateProgressAction((T) state), progressInfo);
                }
                _previousProgressInfo = progressInfo;
            }
    
            public void Report(T value)
            {
                _progressInfo = value;
                if (value.IsCompleted)
                {
                    _timer.Dispose();
                    ProcessUpdate();
                }
            }
        }


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

    var workClass = new WorkClass();
    
                var list = Enumerable.Range(1, 1000).Select(i => i.ToString()).ToArray();
                var progress = new Progress<ProgressInfo>(TimeSpan.FromMilliseconds(100), UpdateProgressAction);
    
                await workClass.LongMethod(list, progress);


    где:

    private void UpdateProgressAction(ProgressInfo obj)
            {
                ProgressBar.Value = obj.CompletedPercentage;
                OperationStatus.Text = obj.ProgressStatusText;
                ProgressBarPercentage.Text = string.Format("{0:P}", obj.CompletedPercentage);
            }
    
    internal class WorkClass
        {
            public async Task LongMethod(IReadOnlyList<string> something, IProgress<ProgressInfo> progress)
            {
                await Task.Factory.StartNew(() =>
                {
                    var count = something.Count;
                    for (int i = 0; i < count; i++)
                    {
                        var element = something[i];
                        Thread.Sleep(5);
                        progress.Report(new ProgressInfo((double)(i + 1) / count, element));
                    }
                });
            }
        }
    Ответ написан
    3 комментария
  • Требует ли синхронизации обращение к статическим полям класса, имеющим значимый тип?

    lam0x86
    @lam0x86
    Блокировки не нужны. Но просто так записывать и читать поля из разных потоков тоже нельзя.
    Вот смотрите: предположим, у вас многопроцессорная система. Один поток выполняется на одном процессоре, другой - на другом. У обоих процессоров есть свой кэш (точнее, несколько уровней кэшей). Если первый поток изменяет переменные (не важно, статические они или нет), то они не попадут в оперативную память до тех пор, пока процессор не сбросит кэш при помощи специальной инструкции. Поэтому, второй поток будет продолжать думать, что данные не изменились.
    Для того, чтобы процессоры правильно работали с такими общими переменными придуманы барьеры памяти (memory barriers). Есть несколько способов поставить такие барьеры:
    1) методы Thread.MemoryBarrier() / Thread.VolatileRead() / Thread.VolatileWrite()
    2) добавить к полю модификатор volatile
    3) использовать методы класса Interlocked
    4) Использование блокирующих примитивов синхронизации (Monitor, ReaderWriterLockSlim, Events, Semaphores, Mutexes, etc.)

    Без контекста задачи не ясно, что вам подойдёт в вашей задаче, но похоже, что достаточно пометить поля модификатором volatile.
    Ответ написан
    4 комментария
  • Алгоритмический вопрос от будущего C#.NET-джуниора. С чего начать исследование?

    lam0x86
    @lam0x86
    Последовательность действий такая:
    1) разбиение текста на лексические единицы (в вашем случае значимыми единицами являются слова). Удобно на выходе получать IEnumerable, представляющий ленивый итератор по словам в тексте.
    2) приведение слова к нормальной форме, т. е. к нижнему регистру и, опционально, к общей словоформе (например, для существительных - им. падеж, ед. число, и т.д.)
    3) добавление слова в Dictionary, где ключом является само слово, а значением - счётчик:
    int count;
    dictionary.TryGetValue(word, out count);
    dictionary[word] = count + 1;
    Ответ написан
    Комментировать
  • Как сконвертировать длинное число (строковое представление в hex) в экспоненциальное представление?

    lam0x86
    @lam0x86
    Можно, например, использовать тип BigInteger (из System.Numerics) для парсинга числа, а затем конвертировать его в double. Только надо заранее удалить префикс "0x".
    var parsedValue = BigInteger.Parse("081a8269359ea02246152537192c7827", NumberStyles.HexNumber);
    var result = (double)parsedValue;
    Ответ написан
    Комментировать
  • Как выстроить приложение .NET с большим числом циклично изменяющихся элементов?

    lam0x86
    @lam0x86
    В RX есть отличный набор классов с общим интерфейсом IScheduler, которые позволяют планировать задачи на исполнение в нужное время и с нужным интервалом. В Вашем случае подойдёт TaskPoolScheduler.
    Но вообще, в играх часто используют подход с обычным циклом, в котором происходит обработка очередного игрового кадра. На каждой итерации определяется игровое время, и на его основе обрабатываются события.
    Ответ написан
    Комментировать
  • Какие посмотреть образцовые open-source проекты на WPF?

    lam0x86
    @lam0x86
    Я бы посоветовал почитать про Prism: msdn.microsoft.com/en-us/library/gg406140.aspx
    Хоть это и не готовое приложение, но из документации можно почерпнуть много полезных шаблонов, которые применяются в разработке под WPF.
    Ответ написан
  • Как для двух combobox использовать один List?

    lam0x86
    @lam0x86
    comboBox1.DataSource = new BindingSource() {DataSource = list};
    comboBox2.DataSource = new BindingSource() {DataSource = list};
    Ответ написан
    Комментировать
  • Как решить данную задачу?

    lam0x86
    @lam0x86
    Не слушай их всех =)
    Наверняка, преподаватель хочет видеть решение с замкнутым связным списком. Что-то вроде такого:
    class Program
        {
            static void Main()
            {
                var personList = GenerateList(15); // personList указывает на первого человека в списке
    
                PrintList(personList);
    
                var p = personList;
                while (p != p.NextPerson) // пока человек не остался один в списке
                {
                    #region Этот кусок для корректного вывода списка на экран. Если вывод не нужен, можно убрать
                    if (personList == p.NextPerson)
                    {
                        personList = p.NextPerson.NextPerson;
                    }
                    #endregion
    
                    // <ВсяСоль>
                    p = p.NextPerson = p.NextPerson.NextPerson;
                    // </ВсяСоль>
    
                    // Если убрать верхний регион, то может возникнуть ситуация, когда personList указывает на 
                    // человека, который был удалён из списка. Возникнет бесконечный цикл.
                    PrintList(personList);
                }
            }
    
            // Вывод списка на консоль
            private static void PrintList(Person personList)
            {
                var p = personList;
                do
                {
                    System.Console.Out.Write(p.SequenceNumber);
                    System.Console.Out.Write(" ");
                    p = p.NextPerson;
                } while (p != personList);
                System.Console.Out.WriteLine();
            }
    
            // Генерация списка
            private static Person GenerateList(int n)
            {
                // Начинаем с последнего человека
                var currentPerson = new Person(n);
                var lastPerson = currentPerson;
    
                // затем создаём N-1 человек, указывая его порядковый номер и следующего за ним человека
                for (int i = n - 1; i > 0; i--)
                {
                    currentPerson = new Person(i) { NextPerson = currentPerson };
                }
    
                // последнего человека закольцовываем с первым
                lastPerson.NextPerson = currentPerson;
                return currentPerson;
            }
        }
    
        class Person
        {
            public Person(int sequenceNumber)
            {
                SequenceNumber = sequenceNumber;
            }
    
            public int SequenceNumber { get; private set; }
    
            public Person NextPerson { get; set; }
        }
    Ответ написан
    Комментировать
  • Как реализовать регулярные выражения в c# ?

    lam0x86
    @lam0x86
    Если вам нужно именно узнать позиции вхождений совпадающих подпоследовательностей, то скорее всего придётся писать свой парсер. Могу посоветовать изучить конечные автоматы, как универсальный способ решения подобных задач (регулярные выражения - это тоже подмножество конечных автоматов). Так же советую погуглить что-то типа "wildcard parsing" - ваша задача очень похожа на стандартные маски.
    Ответ написан
    Комментировать
  • Есть ли такой элемент управления .net OpenSource?

    lam0x86
    @lam0x86
    Можно поинтересоваться, почему не хочется "изобретать велосипед"? Мне кажется, вследствие редкой распространённости подобного функционала, вы, если что-то и найдёте, будете вынуждены городить костыли ради того, чтобы преобразовать вашу модель данных в ту, которая может быть скормлена найденному контролу. Если в процессе эволюции продукта вам необходимо будет добавить функционал, выходящий за пределы возможностей контрола, придётся решать задачу - форкаться от проекта (если он, конечно, open source), и потом иметь боль с каждым новым релизом, либо городить новые костыли, чтобы заставить работать существующую реализацию не так, как это было запланировано создателями.
    В данном случае я бы посоветовал всё же изобрести свой маленький велосипед, тем более, не такой уж и сложный, с виду, должен получиться этот контрольчик.
    Ответ написан
  • Почему падает NotSupportedException в циклах?

    lam0x86
    @lam0x86
    CollectionView создается в WPF автоматически при байндинге коллекций, так что тут ничего странного. Проблема, скорее всего, в том, что вы изменяете вашу коллекцию не из UI потока, например, создав Task и не указав Scheduler, либо используете таймер, отличный от DispatcherTimer, и т. д. Самым простым способом решения проблемы будет обернуть код, изменяющий коллекцию, в вызов Dispatcher.Invoke(...). Главное - указать правильный Dispatcher - его можно получить из любого контрола окна.
    Ответ написан
  • Habrahabr поменял шрифт?

    lam0x86
    @lam0x86
    По-моему, просто размер увеличили.
    Ответ написан
    Комментировать
  • Как правильно определить наличие символов юникода в тексте через RegularExpressions (или иначе) под .Net?

    lam0x86
    @lam0x86
    Когда я вижу сообщения с проблемами в обработке символов "i" и "I" при включенном флаге IgnoreCase, сразу возникает подозрение, что сравнение производится с использованием турецкого языка. В нём "i" строчная преобразуется в заглавную "İ", а заглавная "I" (по-русски читается как "ы") преобразуется в строчную "ı" . Честно признаюсь, не копался глубоко в вашей проблеме, но может мой комментарий натолкнёт вас на что-то.
    Ответ написан
    Комментировать
  • Как задать Placeholder для TextBox в среде VisualStudio 2013 язык C#?

    lam0x86
    @lam0x86
    Если WinForms, то, начиная с WinXP в ОС встроена поддержка данной фичи, и называется это Cue Banners. Здесь написано, как это можно прикрутить: stackoverflow.com/a/4902969

    Если WPF, то можно посмотреть здесь: stackoverflow.com/a/833967
    Ответ написан
    Комментировать
  • Как реализовывается IEnumerable?

    lam0x86
    @lam0x86
    Прошу прощения, но IEnumerable не наследуется от IEnumerator. Ваш код с приведением типа списка к IEnumerator не должен компилироваться. Интерфейсы IEnumerator и IEnumerable тесно интегрированы с компилятором, из-за чего иногда возникает путаница: и тот, и другой интерфейс можно использовать в yield-statements, но по факту в foreach-statements можно использовать только IEnumerable (а на самом деле, всё еще сложнее - в foreach можно использовать вообще любой тип, у которого есть метод GetEnumerator(), но это совсем другая история).
    Ответ написан
  • C# как генерировать символы без повторений?

    lam0x86
    @lam0x86
    Во-первых, в коде баг: rd.Next(0, passwordCombinations.Length - 1)] никогда не вернёт последний символ.

    Во-вторых, Random rd = new Random(); использует Environment.TickCount в качестве seed-а. Если метод вызывается несколько раз в миллисекунду, он вернёт одинаковый результат. Вам нужно создать экземпляр класса Random один раз и передавать его в метод. А ещё лучше - использовать System.Security.Cryptography.RandomNumberGenerator.
    Ответ написан
    Комментировать
  • Как поменять свойство родительского контрола?

    lam0x86
    @lam0x86
    Я бы попробовал использовать TextBox вместо TextBlock:

    <TextBox TextWrapping="Wrap"
             VerticalScrollBarVisibility="Auto"
             IsReadOnly="True"
             Cursor="Arrow"
             Focusable="False"
             BorderThickness="0"
             Text="{Binding FirstInformation}"/>


    И ScrollViewer не нужен в этом случае.
    Ответ написан
    Комментировать