Creating a library with new controls. It has 2 classes "HandySeparator - Basic" and "HandyHSeparator - Derived". The base class inherits the Control class. It contains properties that call the Invalidate() method. In the derived class, inside the OnPaint() method, the element is being drawn.
The catch is that after rebuilding the library, a control with the name of the base class appears in the "Toolbox", but I don't need it there.
** HandySeparator **
public class HandySeparator : Control {
private DashStyle dashStyle;
public DashStyle DashStyle {
get { return dashStyle; }
set {
dashStyle = value;
Invalidate ();
}
}
...
}
** HandyHSeparator **
public class HandyHSeparator : HandySeparator {
...
... OnPaint(...) {
/// Draw element
}
...
}
** HandySeparator **
[ToolboxItem(false)]
public class HandySeparator : Control {
private DashStyle dashStyle;
public DashStyle DashStyle {
get { return dashStyle; }
set {
dashStyle = value;
Invalidate ();
}
}
...
}
** HandyHSeparator **
[ToolboxItem(true)]
public class HandyHSeparator : HandySeparator {
...
... OnPaint(...) {
/// Draw element
}
...
}
Related
This class is used to bind search result in listbox and onselected list it will show result in overview panel, both are two different view model.
public class SearchClients : Client
{
public Client Client;
private void SelectedClient(int PartyId)
{
List<Client> c = this.fileService.FindClients(PartyId, "", "").ToList();
if (c.Count > 0)
{
Client = c[0];
}
OverviewPageViewModel viewModel = this.injector.Resolve<OverviewPageViewModel>("OverviewPage");
viewModel.SelectedClient(Client);
}
}
Search Panel View Model
public class SearchBar : BaseContentViewModel
{
private void FindClients()
{
List<Client> C = fileService.FindClients(0, SrchFirstName, SrchLastName).ToList();
}
public ICommand FindClient
{
get
{
return new RelayCommand(FindClients);
}
}
}
Result Panel View Model
public class OverviewPageViewModel: BaseContentViewModel
{
public void SelectedClient(Client Client)
{
Title = Client.TitleID;
FirstName = Client.FirstName;
LastName = Client.LastName;
}
}
ViewModel was assigned base class IContentViewModel in tab navigation, it should be initiated with OverviewPageViewModel which have all properties. Solved!!
Wrong:
IContentViewModel viewModel = injector.Resolve<IContentViewModel>(TabPage);
Correct:
IContentViewModel viewModel = injector.Resolve<IContentViewModel>(TabPage);
if (TabPage == "OverviewPage")
{
injector.Resolve<ViewModels.Windows.MainWindowViewModel>().CurrentPageViewModel = injector.Resolve<OverviewPageViewModel>(TabPage);
}
else
{
//viewModel.ClearData();
injector.Resolve<ViewModels.Windows.MainWindowViewModel>().CurrentPageViewModel = viewModel;
}
I am trying to access a custom attribute applied to a method within a castle interceptor, but method Attribute.GetCustomAttribute() return null.
public class MyIntecept : Castle.DynamicProxy.IInterceptor
{
public void Intercept(IInvocation invocation)
{
// myAttr is null.
var myAttr = (MyAttribute)Attribute.GetCustomAttribute(
invocation.Method, typeof(MyAttribute));
}
}
[AttributeUsage(AttributeTargets.All, Inherited = true, AllowMultiple = true)]
public class MyAttribute : Attribute
{
readonly string _value;
public MyAttribute(string value)
{
this._value = value;
}
public string Value
{
get { return this._value; }
}
}
public interface IMyInterface
{
void Do();
}
public class MyClass : IMyInterface
{
[MyAttribute("MyValue")]
public void Do()
{
Console.WriteLine("Do");
}
}
How can i get 'MyAttribute'?
P.S. I'am using Castle.Core 3.3.3
Put the attribute "MyAttribute" on the method inside the interface and not inside the class
Given a very basic WinForms custom/user control, using System.Windows.Automation it is possible to manipulate built in properties for the custom control.
This is done like this:
public object GetPropertyValue(int propertyId)
{
if (propertyId == AutomationElementIdentifiers.NameProperty.Id)
{
return "Hello World!";
}
}
What I would like to do is expose custom properties to ui automation such as ReadyState, LastAccessed, Etc.
Is this possible?
No, you can't extend the list of properties, and this is complicated by the fact you use Winforms that has a poor UI Automation support (it uses IAccessible with bridges etc.).
What you can do though is add some fake objects to the automation tree, for example, here is a sample Winforms UserControl that does it:
public partial class UserControl1 : UserControl
{
public UserControl1()
{
InitializeComponent();
Button button = new Button();
button.Location = new Point(32, 28);
button.Size = new Size(75, 23);
button.Text = "MyButton";
Controls.Add(button);
Label label = new Label();
label.Location = new Point(49, 80);
label.Size = new Size(35, 13);
label.Text = "MyLabel";
Controls.Add(label);
MyCustomProp = "MyCustomValue";
}
public string MyCustomProp { get; set; }
protected override AccessibleObject CreateAccessibilityInstance()
{
return new UserControl1AccessibleObject(this);
}
protected class UserControl1AccessibleObject : ControlAccessibleObject
{
public UserControl1AccessibleObject(UserControl1 ownerControl)
: base(ownerControl)
{
}
public new UserControl1 Owner
{
get
{
return (UserControl1)base.Owner;
}
}
public override int GetChildCount()
{
return 1;
}
public override AccessibleObject GetChild(int index)
{
if (index == 0)
return new ValueAccessibleObject("MyCustomProp", Owner.MyCustomProp);
return base.GetChild(index);
}
}
}
public class ValueAccessibleObject : AccessibleObject
{
private string _name;
private string _value;
public ValueAccessibleObject(string name, string value)
{
_name = name;
_value = value;
}
public override AccessibleRole Role
{
get
{
return AccessibleRole.Text; // activate Value pattern
}
}
// note you need to override with member values, base value cannot always store something
public override string Value { get { return _value; } set { _value = value; } }
public override string Name { get { return _name; } }
}
And this is how it appears in the automation tree (using the inspect.exe tool):
Note this technique also supports writing back to the property because it's based on the ValuePattern.
I have the view designed for the long running tasks. It has a header and a progress bar.
So the model has the text for a header and a counter for a progress bar and a TotalAmountOfWork field. The model also has
public delegate void TaskCompleted(string resultDescription);
public event TaskCompletedCopyingCompletedEvent;
public event Action UpdateViewState;
When counters change the model invokes UpdateViewState.
ViewModel is subscribed for the events and updates in it's turn the view.
Ok. I have two classes intended to copy files from a hard disk to a flash drive and one class intended for diagnostic information retrieving and this information should be copied to a flash drive finally too.
I want to use them in the same ViewModel, but I can't figure out how to avoid code repeating. I can't figure out how to make it relying on the proper object oriented design.
Those three classes could implement an interface like this:
interface ILongRunningTask {
void DoWork();
}
And then I can implement ViewModel taking ILongRunningTask as an argument.
But look at the name of the name of the interface. It looks too generalized. It seems that something wrong with such an abstraction.
Ok. It seems to me that ViewModel should take a delegate in order to invoke a long running task. But in this case how the ViewModel will interact with the model updating it's properties?
//update
Now, model looks like:
public class FilesCopyingModel : IFilesCopier {
protected int filesCountToCopy;
public int FilesCountToCopy {
get { return filesCountToCopy; }
set {
filesCountToCopy = value;
InvokeUpdateViewState();
}
}
protected int currentProgressValue;
public int CurrentProgressValue {
get { return currentProgressValue; }
set {
currentProgressValue = value;
InvokeUpdateViewState();
}
}
public delegate void CopyingCompleted(string resultDescription);
public event CopyingCompleted CopyingCompletedEvent;
public event Action UpdateViewState;
private readonly IFilesCopier filesCopier;
protected FilesCopyingModel() {
}
public FilesCopyingModel(IFilesCopier filesCopier) {
if (filesCopier == null)
throw new ArgumentNullException("filesCopier");
this.filesCopier = filesCopier;
}
protected static string GetCurrentDateTime() {
return DateTime.Now.ToString("dd.MM.yyyy hh.mm.ss");
}
protected void InvokeCopyCompletedEvent(string resultDescription) {
if (CopyingCompletedEvent != null)
CopyingCompletedEvent(resultDescription);
}
protected void InvokeUpdateViewState() {
if (UpdateViewState != null)
UpdateViewState();
}
protected DriveInfo GetFirstReadyRemovableDrive() {
return
DriveInfo.GetDrives()
.FirstOrDefault(driveInfo => driveInfo.DriveType == DriveType.Removable && driveInfo.IsReady);
}
public void Copy() {
filesCopier.Copy();
}
}
public interface IFilesCopier {
void Copy();
}
public class KFilesCopier : FilesCopyingModel, IFilesCopier {
private string destinationKFilesDirPath;
public new void Copy() {
//some code
}
private static string ComposeDestinationKFilesDirPath(DriveInfo drive) {
//some code
}
}
public class LogsDirCopier : FilesCopyingModel, IFilesCopier {
public readonly string LogsDirPath;
public LogsDirCopier() {
//some code
}
public new void Copy() {
//some code
}
private void InternalCopyLogsDir(string destinationPath) {
//some code
}
private static void CloseStorer(ZipStorer zipStorer) {
//some code
}
private static string ComposeDestinationArchiveFilePath(string destinationPath) {
//some code
}
private void DetermineLogFilesCount() {
//some code
}
ViewModel interact with infrastructure above like this:
public class FilesCopyingViewModel: Screen {
private readonly FilesCopyingModel model;
private readonly IWindowManager windowManager;
public int CurrentProgress {
get { return model.CurrentProgressValue; }
}
public int FilesCountToCopy {
get { return model.FilesCountToCopy; }
}
[ImportingConstructor]
public LongRunningViewModel(IFilesCopier copier) {
model = copier as FilesCopyingModel;
model.CopyingCompletedEvent += CopyingCompletedHandler;
model.UpdateViewState += UpdateViewStateHandler;
windowManager = new WindowManager();
}
private void UpdateViewStateHandler() {
NotifyOfPropertyChange(() => CurrentProgress);
NotifyOfPropertyChange(() => FilesCountToCopy);
}
private void CopyingCompletedHandler(string resultDescription) {
//some code
}
private void RemoveDriveSafely() {
//some code
}
private void PromptEjection(string result) {
//some code
}
private void PromptSuccessEjection() {
//some code
}
private void PromptEjectFlashError() {
//some code
}
protected override void OnActivate() {
try {
var copier = (IFilesCopier) model;
Task.Factory.StartNew(copier.Copy);
}
catch (Exception ex) {
//error handling
}
}
}
These two classes use "Copy" as the name of the method. Now I want to add one more class with very similar behavior, but it seems that it's method should be named like "CollectDiagnosticInfo". Or maybe I can add a class DiagnosticInfoCopier:IFilesCopier and then just do the same. I really don't know, but the sixth sense suggests that there is a smell of some kind.
In my custom control I have 3 properties(State,Value,Count), State property with Enum(Dock,Float,Tab), if the Enum value(Float) means I want to Hide(Browsable False) Value property in WPF. Is there any possibility to do this with PropertyChanged of the State.
In the setter for State, just check what the value is. If it's Float hide, else unhide.
private StateEnum _state;
public StateEnum State {
get { return _state; }
set
{
if (value == StateEnum.Float)
{
// Hide stuff
}
else
{
// Show stuff
}
name = value;
}
}
Normally you cannot hide a property conditionally.
However, there is a trick.
You can define a value interface and wrapper for your value property and implement for value and nonvalue states.
Example:
public interface IValueWrapper {}
public class BasicValueWrapper : IValueWrapper
{
public int Value { get; set; }
}
public class NoneValueWrapper : IValueWrapper {}
Main Class :
public class MainClass
{
private StateEnum _state;
public StateEnum State {
get { return _state; }
set
{
if (value == StateEnum.Float)
{
// Hide stuff
this.Value= new NoneValueWrapper();
}
else
{
// Show stuff
this.Value= new BasicValueWrapper();
}
name = value;
}
}
public IValueWrapper Value { get; set; }
}