Страницы

Поиск по вопросам

Показаны сообщения с ярлыком usercontrol. Показать все сообщения
Показаны сообщения с ярлыком usercontrol. Показать все сообщения

понедельник, 13 апреля 2020 г.

Зачем в пользовательском контроле поле components?

#c_sharp #visual_studio #usercontrol

                    
При создании нового контрола студия всегда создаёт поле
private System.ComponentModel.IContainer components = null;

но никогда его не использует.
Для чего оно нужно?    


Ответы

Ответ 1



На форму можно положить не только контролы, но и невизуальные компоненты. В то время как контролы при закрытии формы освобождаются автоматически, т.к. форма знает о своих дочерних контролах и прибивает их, компоненты этим свойством не обладают, и их надо закрывать явно. Для этого дизайнер создаёт переменную components и в перекрытом методе Dispose() прибивает компоненты, которые положены на форму. Для того чтобы понять, чем недоволен компилятор, посмотрите на две вещи: 1. Есть ли на форме невизуальные компоненты? 2. Если есть, есть ли среди них компонент, конструктор которого принимает экземпляр IContainer. Правильно написанные компоненты должны иметь именно такой конструктор, который будет генерироваться дизайнером.

Ответ 2



Мой ответ может быть не очень точным. На самом то деле используется, там хранятся ссылки на компоненты (потому что форма это контейнер) и при закрытии формы идет освобождение ресурсов (компонентов). Там в комментариях еще же написано: Required designer variable.

воскресенье, 8 марта 2020 г.

Элемент управления типа UpDown

#c_sharp #winforms #usercontrol


В WinForms есть стандартный контрол NumericUpDown:



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

Какие шаги следует предпринять для достижения нужного эффекта?
    


Ответы

Ответ 1



Попробуйте унаследоваться от предка NumericUpDown: UpDownBase и лимитировать размер контрола размером области кнопок: using System.Windows.Forms; using System.Reflection; using System.Drawing; public class UpDownControl : UpDownBase { private readonly Control upDownButtons; public UpDownControl() { // Достаем internal свойство UpDownButtonsInternal var prop = GetType().GetProperty("UpDownButtonsInternal", BindingFlags.NonPublic | BindingFlags.Instance); if (prop != null) upDownButtons = (Control)prop.GetValue(this, null); } protected override void OnSizeChanged(EventArgs e) { base.OnSizeChanged(e); int gapWidth = Width - upDownButtons.Right + 1; // Либо const int gapWidth = 2; Size = new Size(upDownButtons.Width + gapWidth, upDownButtons.Height); } public override void DownButton() { } public override void UpButton() { } protected override void UpdateEditText() { } } События нажатий на кнопки будут прилетать в методы DownButton и UpButton соответственно.

суббота, 15 февраля 2020 г.

Как выполнить код после загрузки и отображения usercontrol

#vbnet #usercontrol


На форме есть кнопка, при нажатии на которую отображается usercontrol. Если в метод
click кнопки поместить процедуру, то она будет выполняться, затем выход из метода click
и только тогда появляется usercontrol. 

А как сделать чтобы сначала показался usercontrol, а затем начал выполняться код
процедуры?
    


Ответы

Ответ 1



Код нужно поместить в следующую процедуру в самой форме: Private Sub UserForm_Activate() MsgBox "Run after activation (show) of form " End Sub Если вы не хотите чтобы процедура была внутри класса контроля, то создайте процедуру общего доступа (Public) в любом модуле и тоже вызывайте ее из процедуры активации UserForm_Acivate. .. В модуле: Public Sub DoSomethingAfterControlShow() MsgBox "Ok After show" End Sub .. В UserForm: Private Sub UserForm_Activate() DoSomethingAfterControlShow End Sub

Ответ 2



Если я правильно понимаю суть вопроса, то код Private Sub btnShow_Click(sender As Object, e As EventArgs) Handles btnShow.Click MsgBox("Hi") btnUnvisible.Visible = True End Sub выполняется синхронно и контрол btnUnvisible появляется только после нажатия на кнопку "Ок" диалогового окна. Для того, чтобы любой код (в моем случае это msgbox, но может быть вызов любой другой процедуры) выполнялся асинхронно, нужно переписать обработчик события следующим образом: Private Async Sub btnShow_Click(sender As Object, e As EventArgs) Handles btnShow.Click Dim t = New Task(Sub() MsgBox("Hi") ' здесь может быть вызов процедуры или любой другой код End Sub) t.Start() btnUnvisible.Visible = True Await t End Sub В данном случае код внутри Task будет выполнен асинхронно (в другом потоке или в этом же, в зависимости от более оптимального расклада с точки зрения пула потоков), весь код между объявлением объекта Task и ожиданием завершения асинхронной процедуры Await t будет выполнен "параллельно" - таким образом, при нажатии на кнопку будет одновременно отображен другой контрол и показано диалоговое окно

среда, 22 января 2020 г.

Как правильно реализовать функциональность “Поделиться” на подобии как в Google Drive?

#веб_программирование #spring #usercontrol #права #acl


Проектирую сайт, в котором каждый зарегистрированный пользователь, может создавать
записи к примеру как в evernote или в том же google диске.

Всего на сайте есть 4 роли (Админ, Модератор, Поддержка, Пользователь), модель для
реализации выбрал RBAC и каждой роли назначены нужные права.



Но вот не знаю существует ли модель или реализация для Spring для внедрения следующего
функционала:

Каждый пользователь может создавать свои группы в которые может добавлять пользователей
(Друзья, Коллеги по работе, Семья, и т.д.) добавлять может только тех пользователей
которые зарегистрированы на сайте.
Примерно так это вижу в БД:

+------------+---------+--------------+
|   users    | groups  | users_groups |
+------------+---------+--------------+
| id         | id      | id           |
| username   | user_id | group_id     |
| passwords  | name    | user_id      |
+------------+---------+--------------+




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


Доступ по URL (доступен тем у кого есть ссылка)
Публичный доступ (Доступен всем, также виден в поиске)
Публичний с паролем
Группе пользователей
Конкретному зарегистрированному пользователю


Также к каждому шарингу (доступу) будь то пользователю или группе нужно еще выставлять
права:


Только просмотр
Просмотр и редактирование
Полный ( READ / WRITE / DELETE )




Ну и нужно учесть еще такой пункт, к примеру у меня есть записи по работе, создал
группу "Работа" и добавил в нее сотрудников, и группе выдал права на просмотр данной
записи, как быть если я добавляю еще один полный доступ конкретному человеку, но он
также есть в группе для чтения ?

Заранее благодарен за любую помощь или подсказку реализации!
    


Ответы

Ответ 1



У вас есть таблица записей items. Добавьте в нее поле access_mode и заполняйте такими значениями NULL: Только указанные люди Доступ по URL Публичный доступ Публичный с паролем И заведите таблицу список доступа acl с полями id item_id group_id is_read is_write is_delete Для добавления конкретного пользователя можно для него создать виртуальную группу или добавить в таблицу acl поле user_id и заполнять или его или поле group_id (по идее с виртуальными группами будет проще реализация) Т.к. у вас есть только разрешительные права и нет запрещающих, то для вычисления конечных прав пользователя на запись достаточно такого запроса SELECT MAX(is_read), MAX(is_write), MAX(is_delete) FROM acl WHERE item_id = :item_id AND EXISTS ( SELECT 1 FROM users_groups ug WHERE ug.user_id = :user_id AND ug.group_id = acl.group_id )

пятница, 10 января 2020 г.

Как прикрепить ViewModel к UserControl?

#c_sharp #net #wpf #mvvm #usercontrol


Как прикрепить ViewModel к UserControl? В случае с window всегда делал так:

        new MainWindow()
        {
            DataContext = new MainVm()
        };


Если делать так для UserControl то компилятор ругается. Как нужно действовать в данной
ситуации?

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


Ответы

Ответ 1



Контрол не должен устанавливать себе сам DataContext. DataContext должен устанавливать родительский элемент. Делайте как-то так: То есть: нужные VM для частей, которые представляются в виде контролов, должны быть в MainVM как свойства. (Таким образом, кстати, все VM смогут общаться через центральную VM.) Надеюсь, вы поняли идею. Кстати, и главное окно тоже не должно создавать себе VM. Обычно делается так: public partial class App : Application { MainVM mainVM = new MainVM(); protected override void OnStartup(StartupEventArgs e) { base.OnStartup(e); new MainWindow() { DataContext = mainVM }.Show(); } }

понедельник, 15 июля 2019 г.

UserControlVIewModel работа со свойствами UserControl

Имеется главная MainViewModel и MyUserControl(у него своя ViewModel).
public class MainViewModel { public ObservableCollection StringList; public MainViewModel() { StringList = new ObservableCollection(); } }
Допустим необходимо передать коллекцию строк из MainViewModel в UserControl.

как получить коллекцию StringList во ViewModel-и MyUserControl-а?
public class MyUserControlVM { //здесь работать с Items который приходит от MyUserControl }
UPD1
Но вопрос ещё вот в чём: зачем другому контролу видеть те же Items? Какой объект этот контрол визуализирует? Если это тот же объект, то и VM та же. Если это другой объект, почему у двух объектов общая часть?
Отвечаю на вопрос, да это другой объект.
Может быть такое что несколько UserControl-ов принимают одни и те же данные и обрабатывают их по своему в своих VM, затем выводят результат во View

Добавим еще один MyUserControl2(со своей VM), который также принимает коллекцию StringList из MainVM. Каждый контрол по-своему обрабатывает принимаемую коллекцию, и выводит во View результат обработки.
Первый UserControl


Второй UserControl


В итоге для того чтобы работал UserControl ему нужно передать некую информацию из MainVM, затем работать с ней во VM-контрола. Собственно как обращаться к этой некой информации во VM контрола? Или как получить данные от DependecyProperty(определенные в контроле) во VM контрола.


Ответ

Проблема вот в чём: вы задаёте DataContext прямо внутри контрола! Так делать не стоит, ведь при этом он у вас будет не связан с внешним миром. Вы должны устанавливать DataContext снаружи, как-то так:

где SubVM — свойство типа MyUserControlVM в MainViewModel
Если несколько контролов должны иметь доступ к общей коллекции, положите ссылку на одну и ту же коллекцию в их VM. Если вы создаёте подчинённые VM не из XAML'а, а вручную, вы можете правильно инициализировать их и связать нужным вам образом.

суббота, 6 июля 2019 г.

Зачем в пользовательском контроле поле components?

При создании нового контрола студия всегда создаёт поле private System.ComponentModel.IContainer components = null; но никогда его не использует. Для чего оно нужно?


Ответ

На форму можно положить не только контролы, но и невизуальные компоненты. В то время как контролы при закрытии формы освобождаются автоматически, т.к. форма знает о своих дочерних контролах и прибивает их, компоненты этим свойством не обладают, и их надо закрывать явно. Для этого дизайнер создаёт переменную components и в перекрытом методе Dispose() прибивает компоненты, которые положены на форму. Для того чтобы понять, чем недоволен компилятор, посмотрите на две вещи: 1. Есть ли на форме невизуальные компоненты? 2. Если есть, есть ли среди них компонент, конструктор которого принимает экземпляр IContainer. Правильно написанные компоненты должны иметь именно такой конструктор, который будет генерироваться дизайнером.

четверг, 30 мая 2019 г.

Как прикрепить ViewModel к UserControl?

Как прикрепить ViewModel к UserControl? В случае с window всегда делал так:
new MainWindow() { DataContext = new MainVm() };
Если делать так для UserControl то компилятор ругается. Как нужно действовать в данной ситуации?
P.S. Для общей картины обьясню к какому эффекту я стремлюсь: есть главное окно, и в зависимости от нажатий пользователся должны отображатся разные, никак не связанные между собой данные. Поэтому для каждых из этих данных я хочу создать отдельные UserControl и Vm, и по надобности просто подменять один UserControl на другой. Если у меня неправильный подход, поправьте меня.


Ответ

Контрол не должен устанавливать себе сам DataContext. DataContext должен устанавливать родительский элемент. Делайте как-то так:

То есть: нужные VM для частей, которые представляются в виде контролов, должны быть в MainVM как свойства. (Таким образом, кстати, все VM смогут общаться через центральную VM.)
Надеюсь, вы поняли идею.

Кстати, и главное окно тоже не должно создавать себе VM. Обычно делается так:


public partial class App : Application { MainVM mainVM = new MainVM();
protected override void OnStartup(StartupEventArgs e) { base.OnStartup(e); new MainWindow() { DataContext = mainVM }.Show(); } }

вторник, 28 мая 2019 г.

Элемент управления типа UpDown

В WinForms есть стандартный контрол NumericUpDown

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


Ответ

Попробуйте унаследоваться от предка NumericUpDown: UpDownBase и лимитировать размер контрола размером области кнопок:
using System.Windows.Forms; using System.Reflection; using System.Drawing;
public class UpDownControl : UpDownBase { private readonly Control upDownButtons;
public UpDownControl() { // Достаем internal свойство UpDownButtonsInternal var prop = GetType().GetProperty("UpDownButtonsInternal", BindingFlags.NonPublic | BindingFlags.Instance); if (prop != null) upDownButtons = (Control)prop.GetValue(this, null); }
protected override void OnSizeChanged(EventArgs e) { base.OnSizeChanged(e); int gapWidth = Width - upDownButtons.Right + 1; // Либо const int gapWidth = 2; Size = new Size(upDownButtons.Width + gapWidth, upDownButtons.Height); }
public override void DownButton() { }
public override void UpButton() { }
protected override void UpdateEditText() { } }
События нажатий на кнопки будут прилетать в методы DownButton и UpButton соответственно.