I am trying to do something similar as UserInteractionEnabled = false in iOS, but it seems that this property is not available in NSView. I also see that one approach is to implement the hittest method to return null, but the hittest for this lass already has a non-trivial implementation and I don't think I can set it to return null. I found a (deprecated) property called acceptsTouchEnabled, and I m wondering if it can achieve the same thing as UserInteractionEnabled.
The project is done in Xamarin, btw.
FreeHandView = new PaintBoardControl
{
BackgroundColor = UIColor.Clear,
TranslatesAutoresizingMaskIntoConstraints = false,
UserInteractionEnabled = false
};
this is the original declaration of the variable, where the UserInteractionEnabled is set to false.
and this is the implementation of the hittest method in my Mac app:
public override NSView HitTest(CGPoint aPoint)
{
aPoint = ContentContainer.ConvertPointFromView(aPoint, this);
aPoint = new CGPoint(aPoint.X + _freehandViewLeftConstraint.Constant,
aPoint.Y + _freehandViewTopConstraint.Constant);
if (_hitTestBitArray != null && aPoint.X >= 0 && aPoint.Y >= 0 &&
_hitTestBitArrayWidth > aPoint.X && _hitTestBitArrayHeight > aPoint.Y)
{
var index = aPoint.Y * _hitTestBitArrayWidth + aPoint.X;
return _hitTestBitArray.Get((int)index) ? this : null;
}
return null;
}
Sometimes hitTest don't work at all try using something like this maybe mousedown can help you
public class ExtendedNSView : NSView
{
public bool IsEnabled { get; set; }
public override void MouseDown(NSEvent theEvent)
{
if (IsEnabled)
{
base.MouseDown(theEvent);
}
}
}
Related
I am working on a project using MvvmCross and Xamarin. I am trying to add a custom transition when presenting and dismissing my modal view. Currently I am presenting it this way:
[MvxModalPresentation(WrapInNavigationController = true, ModalPresentationStyle = UIModalPresentationStyle.Custom)]
public partial class MyView : MvxViewController
{
and dismissing it this way:
NavigationController.DismissModalViewController(true);
So I have my animation ready, but I am assuming that I need to set the transition delegate to the one I've created. How do I do this?
I am fairly new to MvvmCross, so any tips and tricks are very much appreciated. Thanks!
I Am not sure, what you actually want to achieve here.
If you are looking for syntax help. This should be something like this.
this.NavigationController.TransitioningDelegate = new MyOwnDelegate();
internal class MyOwnDelegate : IUIViewControllerTransitioningDelegate
{
public IntPtr Handle => throw new NotImplementedException();
public void Dispose()
{
//throw new NotImplementedException();
}
}
But normally people use, this one. I am also giving some syntax if that helps
this.NavigationController.Delegate = new NavigationControllerDelegate();
public class NavigationControllerDelegate : UINavigationControllerDelegate
{
public NavigationControllerDelegate(IntPtr handle) : base(handle)
{
}
public NavigationControllerDelegate()
{
}
public override IUIViewControllerAnimatedTransitioning GetAnimationControllerForOperation(UINavigationController navigationController, UINavigationControllerOperation operation, UIViewController fromViewController, UIViewController toViewController)
{
var fromVcConformA = fromViewController as ICustomTransition;
var fromVCConFromB = fromViewController as IWaterFallViewControllerProtocol;
var fromVCCConformc = fromViewController as IHorizontalPageViewControllerProtocol;
var toVcConformA = toViewController as ICustomTransition;
var toVCConfromB = toViewController as IWaterFallViewControllerProtocol;
var toVCCConformc = toViewController as IHorizontalPageViewControllerProtocol;
if ((fromVcConformA != null) && (toVcConformA != null) && ((fromVCConFromB != null && toVCCConformc != null) || (fromVCCConformc != null && toVCConfromB != null)))
{
var transition = new CustomTransition();
transition.presenting = operation == UINavigationControllerOperation.Pop;
return transition;
}
else
{
return null;
}
}
}
So I have a boolean method that is used to verify if a command is valid. This is used inside of an engine in which it verifies that the process can continue or not. This is the validation method:
private bool CommandIsValid(WC command)
{
if (command.Address == null ||
command.UserId < 0 ||
String.IsNullOrEmpty(command.CurrencyCode) ||
command.Amount < .01m ||
command.Address.PrimitiveAddress == null ||
String.IsNullOrEmpty(command.Address.Source) ||
String.IsNullOrEmpty(command.Address.PrimitiveAddress.City) ||
String.IsNullOrEmpty(command.Address.PrimitiveAddress.Country) ||
String.IsNullOrEmpty(command.Address.PrimitiveAddress.FirstName) ||
String.IsNullOrEmpty(command.Address.PrimitiveAddress.LastName) ||
String.IsNullOrEmpty(command.Address.PrimitiveAddress.Region) ||
command.Address.Created <= DateTime.MinValue)
{
return false;
}
return true;
}
And is called here inside of my method here:
if (!CommandIsValid(cmd))
{
_logger.Debug("Invalid command);
}
The issue is that I want to have some type of information regarding what failed validation. The best solution would have a list of what validations didn't pass, so I could relay that in my logging debugger. Obviously I could do this using a bunch of if-else statements, but it seems sloppy, as having a bunch of if else statements seems very poor style and I was wondering if there is any way in c# or in general I can do to avoid this.
Are you familiar with DataAnnotations and it's associated Validator class?
It would require modifications to your object.
public PrimitiveAddress
{
[Required]
public string City {get;set;}
}
and then you use it like so:
var context = new ValidationContext(command.Address.PrimitiveAddress);
var results = new List<ValidationResult>();
var isValid = Validator.TryValidateObject(recipe, context, results);
if (!isValid)
{
foreach (var validationResult in results)
{
Console.WriteLine(validationResult.ErrorMessage);
}
}
if you've got a base command class you could probably add it in a more generic fashion. You can create your own validation attributes, use IValidatableObject for anything complex, customize the error messages
[Required(ErrorMessage="This is required.")]
Instead of returning a bool, return a container of bool values where first is the overall status False/True then each one reflects a condition of the above. If first element is False, then you check which condition (index) is the false. Looks like it is fixed in size then you may just agree on the sequence.
Something like this:
List<bool> YourFunction(YourDebuggerThing Input)
{
List<bool> Result = new List<bool>();
if (Input.Condition1 == false || Input.Condition2 == false || Input.Condition3 == false || Input.Condition4 == false || Input.Condition5 == false)
Result.Add(false); // first element is always the overall status
if(Input.Condition1 == false) Result.Add(false); else Result.Add(true); // element 2 is condition 1
if(Input.Condition2 == false) Result.Add(false); else Result.Add(true); // element 3 is condition 2
// ..
// ConditionN
return Result;
}
One idea might be to implement your checks within the Get/Set methods of the class' properties, using a custom exception. Such as;
public class PrimitiveAddresses
{
private string _city;
public string City
{
get
{
if(_city != null) {return _city;}
else {throw new CommandInvalidException("No valid city provided");}
}
set
{
_city = value;
}
}
}
public class CommandInvalidException: Exception
{
public CommandInvalidException(string message)
: base(message)
{
}
}
Then during you implementation, use a try/catch to handle the specific error;
public void foo()
{
try
{
if (String.IsNullOrEmpty(command.Address.PrimitiveAddress.City)){} // Ect
}
catch (CommandInvalidException e)
{
Console.WriteLine("Command invalid due to " + e.message);
// Or any other way you want to deal with the missing data
}
}
Hope it helps :)
I have created custom button in winforms in which i've added property with a list of custom class: List<Zasoby> and a method to add item to this list only when there is already item in that list that meets specific criteria (the lambda .where expression).
The class Zasob is serializable.
And in designer i add first Zasob to the list in this button like this:
bt01008xxx.Zasoby.Add(new Zasob { Lokalizacja = new Lokalizacja("01", "008", "000") });
..
public class ZasobSzczegolowoButton: Button, IAddZasoby
{
private List<Zasob> _zasoby = new List<Zasob>(); //{ new Zasob { Lokalizacja = new Lokalizacja("01", "001", "000") } };
[EditorBrowsable(EditorBrowsableState.Always)]
[Browsable(true)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
[Bindable(true)]
public List<Zasob> Zasoby
{
get { return _zasoby; }
set
{
_zasoby = value;
if (_zasoby.Any()) BackColor = _zasoby.Sum(x => x.Ilosc) > 0 ? Color.Coral : Color.White;
}
}
public void AddZasoby(List<Zasob> zasoby)
{
var buton = Name;
if (_zasoby != null && _zasoby.Count != 0)
{
var szukaneZasoby =
zasoby?.Where(
x =>
x.Lokalizacja.ObszarKod == _zasoby[0].Lokalizacja.ObszarKod &&
x.Lokalizacja.Segment1 == _zasoby[0].Lokalizacja.Segment1);
if (szukaneZasoby == null) return;
Zasoby.Clear();
Zasoby.AddRange(szukaneZasoby);
}
}
}
...
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Delegate,Inherited = false)]
[ComVisible(true)]
public class Zasob : Attribute
{
public Towar Towar { get; set; }
public Magazyn Magazyn { get; set; }
public Lokalizacja Lokalizacja { get; set; }
public decimal Ilosc { get; set; }
}
Now whenever i try to use method AddZasoby i get System.ArgumentOutOfRangeException. I check the list for null and count items and in debug mode and it shoud exit method but still somehow ends up in the body of the method with the error. (please see the screenshot below)
Any idea what am i doing wrong?
You check the list correctly for the count but with the code Zasoby.Clear(); you clear those elements from the member variable _zasoby again.
Don't let it trick yourself: You're defining the Where()-clause before you clear the list but it will be executed afterwards! That's the trick with lambdas, the predicates you wrote in your Where()-lambda will just be executed as soon as it is evaluated.
This feature is called Deferred Execution, see the first example here.
To fix that, you can enforce the lambda to be executed immediately by calling ToArray() or ToList() before you clear your list like:
public void AddZasoby(List<Zasob> zasoby)
{
var buton = Name;
if (_zasoby != null && _zasoby.Count != 0)
{
var szukaneZasoby =
zasoby?.Where(
x =>
x.Lokalizacja.ObszarKod == _zasoby[0].Lokalizacja.ObszarKod &&
x.Lokalizacja.Segment1 == _zasoby[0].Lokalizacja.Segment1
).ToList(); // *** NOTE ME HERE ***
if (szukaneZasoby == null) return;
Zasoby.Clear();
Zasoby.AddRange(szukaneZasoby);
}
}
That should do the trick.
I want to make a carousel that's linear WITH wrap enabled (so you can scroll indefinitely in either direction and it'll just wrap around) They have a CarouselType.Linear, but it isn't wrap enabled. Anyone know of how to do this with either iCarousel or UICollectionViews? I can't find any good resources on how to make a Custom iCarousel layout... Any good references there?
Alliance Carousel
this.Carousel = new CarouselView(frame)
{
DataSource = new CylindericalDataSource(this),
Delegate = new CylindericalDelegate(this)
};
this.Carousel.CarouselType = CarouselType.Linear;
this.Carousel.ConfigureView();
this.View.AddSubview(this.Carousel);
------------EDIT--------------
To answer #Rahul's question
public override void DidScroll (CarouselView carouselView)
{
base.DidScroll (carouselView);
nint numOfItems = carouselView.NumberOfItems;
if (this._parentController != null &&
this._parentController._studioViewController != null &&
this._parentController._studioViewController.SuccessfullyReceivedProjectAndPageData () &&
this._parentController._studioViewController.HasFlowCardCarouselFinishedLoading () &&
numOfItems > 0)
{
// Enforce min and max values fro ScrollOffset so the user can't scroll the carousel off screen. This is required when wrapping is turned off.
nfloat maxScrollOffset = ((nfloat)numOfItems) - 1f;
nfloat minScrollOffset = 0f;
if (carouselView.ScrollOffset < minScrollOffset)
{
carouselView.ScrollOffset = minScrollOffset;
}
if (carouselView.ScrollOffset > maxScrollOffset)
{
carouselView.ScrollOffset = maxScrollOffset;
}
}
}
Figured it out. Override the ValueForOption method and force the CarouseOption.Wrap to be equal to 1.0f. See below
/*--------------------------------------------------------------------------------*/
// Class: CylindericalDelegate
/*--------------------------------------------------------------------------------*/
public class CylindericalDelegate : CarouselViewDelegate
{
/*--------------------------------------------------------------------------------*/
// Constructors
/*--------------------------------------------------------------------------------*/
public CylindericalDelegate()
{
}
/*--------------------------------------------------------------------------------*/
// CylindericalDelegate Implementation
/*--------------------------------------------------------------------------------*/
public override nfloat ValueForOption(CarouselView carousel, CarouselOption option, nfloat aValue)
{
if (option == CarouselOption.Spacing)
{
return aValue * 1.1f;
}
if (option == CarouselOption.Wrap)
{
return 1.0f;
}
return aValue;
}
/*--------------------------------------------------------------------------------*/
}
/*--------------------------------------------------------------------------------*/
For very special circumstances, I'd like to be able to store C# code in a configuration entry and fill in an empty function with this code at runtime. For example, let's say on initial run I start out with a method such as this:
bool Evaluate(int number)
{
return false;
}
I have a configuration entry that looks like this:
<add key="EvaluateCode" value="if (number > 5) { return true; } else { return false; }"/>
After loading the EvaluateCode configuration entry I'd like to replace the function body of Evaluate so that it looks like this:
bool Evaluate(int number)
{
if (number > 5) { return true; } else { return false; }
}
After this 'replacement' is made, the Evaluate function should behave as the code dictates, just as it would as if the code had not been loaded dynamically.
How could I acheive this in C#?
Bonus: What would be the risks of implementing such a feature? How can I mitigate those risks?
Essentially you are asking for the ability to compile c# code at run time, which is possible, and is described here
This sounded like fun.. so I decided to try it.
No need to upvote.. just popping this here so I can reference it in future :)
Given the below class:
class DynamicMethodTest {
private MethodInfo _methodToCall;
private object _obj;
public void PerformInjection(string newBody) {
using (var codeProvider =
new Microsoft.CSharp.CSharpCodeProvider()) {
var res = codeProvider.CompileAssemblyFromSource(
new System.CodeDom.Compiler.CompilerParameters() {
GenerateInMemory = true
},
"public class StubClass { public bool Evaluate(int number) { " + newBody + " }}"
);
var type = res.CompiledAssembly.GetType("StubClass");
_obj = Activator.CreateInstance(type);
_methodToCall = _obj.GetType().GetMethod("Evaluate");
}
}
public bool Evaluate(int number) {
if (_methodToCall != null)
return (bool)_methodToCall.Invoke(_obj, new object[] { number });
return false;
}
}
We can do this:
public class Program {
public static void Main() {
var dynamicTest = new DynamicMethodTest();
Console.WriteLine(dynamicTest.Evaluate(15)); // False
dynamicTest.PerformInjection("if (number > 5) { return true; } else { return false; }");
Console.WriteLine(dynamicTest.Evaluate(15)); // True
Console.Read();
}
}
This results in:
False
True
As output. Basically, before the "Injection" (its not really injection.. its more of a fascade) the method returns false. After "Injection" it returns true (as expected).