События (C#).NET - пользовательский вопрос о EventArgs

У меня есть много пользовательских событий C#, которые связаны с объектами, выбираемыми в дереве и затем контекстном меню, используемом для инициирования некоторого действия с выбранными пунктами. Я начал создавать отдельный находящийся в EventArgs класс для каждого пользовательского события, упаковывать необходимые данные для события.

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

Имея это в виду, интересно, является ли любое из следующего приемлемой практикой?

  • Используйте тот же пользовательский находящийся в EventArgs класс для нескольких событий (те, которым просто нужен список объектов, который будет передан). Очевидно, это должно работать, но, кажется, покончило с некоторыми рекомендуемыми соглашениями о присвоении имен, используемыми для проводного соединения оборудования события.

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

  • Возможно, что-то еще полностью?

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

Спасибо за любой совет.

5
задан Dan McGrath 8 February 2010 в 19:27
поделиться

4 ответа

Ниже приведен полный пример отображения данных с линейной оси на окружность.

Я показываю два способа достижения цели:

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

Основная идея: если у вас есть ряд D , то сопоставьте точки с окружностью, где радиус равен значениям данных, используя:

theta = linspace(0, 2*pi, N);    %# divide circle by N points (length of data)
r = data;                        %# radius
x = r.*cos(theta);               %# x-coordinate
y = r.*sin(theta);               %# y-coordinate
plot(x, y, '-');

Опция 1

%# some random data
K = 3;
N = 30;
data = zeros(K,N);
data(1,:) = 0.2*randn(1,N) + 1;
data(2,:) = 0.2*randn(1,N) + 2;
data(3,:) = 0.2*randn(1,N) + 3;

center = [0 0];                        %# center (shift)
radius = [data data(:,1)];             %# added first to last to create closed loop
radius = normalize(radius',1)'+1;      %# normalize data to [0,1] range

figure, hold on

%# draw outer circle
theta = linspace(5*pi/2, pi/2, 500)';  %# 'angles
r = max(radius(:));                    %# radius
x = r*cos(theta)+center(1);
y = r*sin(theta)+center(2);
plot(x, y, 'k:');

%# draw mid-circles
theta = linspace(5*pi/2, pi/2, 500)';  %# 'angles
num = 5;                               %# number of circles
rr = linspace(0,2,num+2);              %# radiuses
for k=1:num
    r = rr(k+1);
    x = r*cos(theta)+center(1);
    y = r*sin(theta)+center(2);
    plot(x, y, 'k:');
end

%# draw labels
theta = linspace(5*pi/2, pi/2, N+1)';    %# 'angles
theta(end) = [];
r = max(radius(:));
r = r + r*0.2;                           %# shift to outside a bit
x = r*cos(theta)+center(1);
y = r*sin(theta)+center(2);
str = strcat(num2str((1:N)','%d'),{});   %# 'labels
text(x, y, str, 'FontWeight','Bold');

%# draw the actual series
theta = linspace(5*pi/2, pi/2, N+1);
x = bsxfun(@times, radius, cos(theta)+center(1))';
y = bsxfun(@times, radius, sin(theta)+center(2))';
h = zeros(1,K);
clr = hsv(K);
for k=1:K
    h(k) = plot(x(:,k), y(:,k), '.-', 'Color', clr(k,:), 'LineWidth', 2);
end

%# legend and fix axes
legend(h, {'M1' 'M2' 'M3'}, 'location', 'SouthOutside', 'orientation','horizontal')
hold off
axis equal, axis([-1 1 -1 1] * r), axis off

option1

Опция 2

%# some random data
K = 3;
N = 30;
data = zeros(K,N);
data(1,:) = 0.2*randn(1,N) + 1;
data(2,:) = 0.2*randn(1,N) + 2;
data(3,:) = 0.2*randn(1,N) + 3;

center = [0 0];                                %# center (shift)
radius = [data data(:,1)];                     %# added first to last to create closed loop
radius = normalize(radius',1)';                %# normalize data to [0,1] range
radius = bsxfun( @plus, radius, (1:2:2*K)' );  %# 'make serieson seperate ranges by addition

figure, hold on

%# draw outer circle
theta = linspace(5*pi/2, pi/2, 500)';   %# 'angles
r = max(radius(:))+1;                   %# radius
x = r*cos(theta)+center(1);
y = r*sin(theta)+center(2);
plot(x, y, 'k:');

%# draw mid-circles
theta = linspace(5*pi/2, pi/2, 500)';  %# 'angles
r = 1.5;                               %# radius
for k=1:K
    x = r*cos(theta)+center(1);
    y = r*sin(theta)+center(2);
    plot(x, y, 'k:');
    r=r+2;             %# increment radius for next circle
end

%# draw labels
theta = linspace(5*pi/2, pi/2, N+1)';    %# 'angles
theta(end) = [];
r = max(radius(:))+1;
r = r + r*0.2;                           %# shift to outside a bit
x = r*cos(theta)+center(1);
y = r*sin(theta)+center(2);
str = strcat(num2str((1:N)','%d'),{});   %# 'labels
text(x, y, str, 'FontWeight','Bold');

%# draw the actual series
theta = linspace(5*pi/2, pi/2, N+1);
x = bsxfun(@times, radius, cos(theta)+center(1))';
y = bsxfun(@times, radius, sin(theta)+center(2))';
h = zeros(1,K);
clr = hsv(K);
for k=1:K
    h(k) = plot(x(:,k), y(:,k), '.-', 'Color', clr(k,:), 'LineWidth', 2);
end

%# legend and fix axes
legend(h, {'M1' 'M2' 'M3'}, 'location', 'SouthOutside', 'orientation','horizontal')
hold off
axis equal, axis([-1 1 -1 1] * r), axis off

option2


Следует отметить, что normalize () является пользовательской функцией, она просто выполняет нормализацию minmax ( (x-min )/( max-min) ), определяемую как:

function newData = normalize(data, type)
    [numInst numDim] = size(data);
    e = ones(numInst, 1);
    minimum = min(data);
    maximum = max(data);
    range = (maximum - minimum);

    if type == 1
        %# minmax normalization: (x-min)/(max-min)   =>   x in [0,1]
        newData = (data - e*minimum) ./ ( e*(range+(range==0)) );
    end

    %# (...)
end
-121--4617230-

Из связанного вопроса, который конкретно просил решение быть pythonic, вы должны попробовать в библиотеке motmot's camiface от Эндрю Стро. Он также работает с камерами firewire, но он также работает с виджетом, который вы ищете.

Из учебного пособия:

import motmot.cam_iface.cam_iface_ctypes as cam_iface
import numpy as np

mode_num = 0
device_num = 0
num_buffers = 32

cam = cam_iface.Camera(device_num,num_buffers,mode_num)
cam.start_camera()
frame = np.asarray(cam.grab_next_frame_blocking())
print 'grabbed frame with shape %s'%(frame.shape,)
-121--3855367-

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

5
ответ дан 13 December 2019 в 22:07
поделиться

Вы имеете в виду что-то вроде

public class EventArgs<TValue> : EventArgs
{
    public TValue Value { get; }

    /* ... */
}

?

Где я могу использовать в качестве значения все, что мне нравится?

Да, Я с удовольствием пользуюсь такой штукой. Не думаю, что это проблема.

1
ответ дан 13 December 2019 в 22:07
поделиться

Я бы выбрал и один, и два. Создайте базовый класс, который вы можете использовать для большинства ваших событий, а затем наследовать от этого класса для событий, которым нужно что-то еще. Если вы посмотрите на библиотеки .NET, именно так они были созданы.

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

1
ответ дан 13 December 2019 в 22:07
поделиться

Существует много примеров этого в рамке.NET. Это было бы довольно последовательно, чтобы сделать что-то в том же направлении. Вот пара:

  • Система. ComponentModel. ProgressChangedEventArgs (обеспечивает ProgressPercentage и UserState к производным типам),
    • Система. Сеть. Система DownloadProgressChangedEventArgs
    • . Сеть. Система UploadProgressChangedEventArgs
    • . Windows. Документы. Сериализация. Система WritingProgressChangedEventArgs
  • . ComponentModel. CancelEventArgs (обеспечивает Отмена член к производным типам),
    • Microsoft. VisualBasic. ApplicationServices. Система StartupEventArgs
    • . ComponentModel. Система DoWorkEventArgs
    • . Конфигурация. Система SettingChangingEventArgs
    • . Рисование. Печать. Система PrintEventArgs
    • . Сеть. UI.WebControls. Система DetailsViewDeleteEventArgs
    • . Сеть. UI.WebControls. Система DetailsViewInsertEventArgs
    • . Сеть. UI.WebControls. Система DetailsViewModeEventArgs
    • . Сеть. UI.WebControls. Система DetailsViewPageEventArgs
    • . Сеть. UI.WebControls. Система DetailsViewUpdateEventArgs
    • . Сеть. UI.WebControls. EntityDataSourceChangingEventArgs
    • Буквально еще 50 из этих

Редактирование:

я мог бы использовать класс как это ( не краткий обзор).

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;

public class CollectionEventArgs<T> : EventArgs
{
    public static readonly CollectionEventArgs<T> Empty = new CollectionEventArgs<T>();

    public CollectionEventArgs(params T[] items)
    {
        this.Items = new ReadOnlyCollection<T>(items);
    }

    public CollectionEventArgs(IEnumerable<T> items)
    {
        this.Items = new ReadOnlyCollection<T>(items.ToArray());
    }

    public ReadOnlyCollection<T> Items
    {
        get;
        private set;
    }
}
3
ответ дан 13 December 2019 в 22:07
поделиться
Другие вопросы по тегам:

Похожие вопросы: