|
I created an attached property of type List<string>. How do you assign list items to the collection in XAML?
<h1>region MyItems Collection</h1>
public static readonly DependencyProperty MyItemsProperty =
DependencyProperty.RegisterAttached("MyItems",
typeof(List<string>),
typeof(MyClass),
new UIPropertyMetadata(null,
new PropertyChangedCallback(OnMyItemsChanged)));
public static List<string> GetMyItems(DependencyObject obj)
{
return (List<string>)obj.GetValue(RightsKeyProperty);
}
public static void SetMyItems(DependencyObject obj, List<string> value)
{
obj.SetValue(MyItemsProperty, value);
}
private static void OnMyItemsChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
{
}
<h1>endregion</h1>
<blockquote class="quote"><div class="op">Quote:</div><TextBox Grid.Row="1"
Grid.Column="1"
Text="{Binding CreditLimit, Mode=TwoWay}"
Width="100"
sec:MyClass.MyItems="" <!--HOW DO I ASSIGN MULTIPLE ITEMS HERE-->
HorizontalAlignment="Left"
Margin="10"/>
</blockquote>
If it's not broken, fix it until it is.
Everything makes sense in someone's mind.
Ya can't fix stupid.
|
|
|
|
|
If I've guessed what you're trying to do correctly, something like this should work:
<TextBox ...>
<sec:MyClass.MyItems>
<sys:String>Item 1</sys:String>
<sys:String>Item 2</sys:String>
...
</sec:MyClass.MyItems>
</TextBox>
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
Thanks
is that possible on one line? Maybe {"Item1, Item2"}?
If it's not broken, fix it until it is.
Everything makes sense in someone's mind.
Ya can't fix stupid.
|
|
|
|
|
|
I'm doing something wrong here. The Getter is called, but neither the Setter nor the callback arn't being called.
My DP
public static readonly DependencyProperty RightKeysProperty =
DependencyProperty.RegisterAttached("InternalRightKeys",
typeof(List<string>),
typeof(AppSecurity),
new UIPropertyMetadata(new List<string>(),
new PropertyChangedCallback(OnRightKeysChanged)));
public static List<string> GetRightKeys(DependencyObject obj)
{
return (List<string>)obj.GetValue(RightKeysProperty);
}
public static void SetRightKeys(DependencyObject obj, List<string> value)
{
obj.SetValue(RightKeysProperty, value);
}
private static void OnRightKeysChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
{
}
My XAML
<TextBox Grid.Row="1"
Grid.Column="1"
Text="{Binding CreditLimit, Mode=TwoWay}"
Width="100"
HorizontalAlignment="Left"
Margin="10">
<sec:AppSecurity.RightKeys>
<sys:String>Item 1</sys:String>
<sys:String>Item 2</sys:String>
</sec:AppSecurity.RightKeys>
</TextBox>
Again, nothing is being called. I get no errors or messages in output
If it's not broken, fix it until it is.
Everything makes sense in someone's mind.
Ya can't fix stupid.
|
|
|
|
|
That's the expected behaviour for any dependency property set via XAML:
Important: Do not add any logic to these properties, because they are only called when you set the property from code. If you set the property from XAML the SetValue() method is called directly.
The OnRightKeysChanged method should still be called.
NB: You might need to fix the name of the property so that it matches the standard pattern. Since you've declared RightKeysProperty , it should be called "RightKeys" , not "InternalRightKeys" .
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
Hello All,
Please how do i emplment the WPF equivalent of
public FooClickArgs(NFoo pos, NFoo2 part, MouseEventArgs e)
: base(e.Button, e.Clicks, e.X, e.Y, e.Delta)
{
Position = pos;
PositionPart = part;
}
In WPF Canvas.
Thank you.
|
|
|
|
|
Canvases (say it really fast a few times) don't respond to events; because they cannot have focus and so forth.
"(I) am amazed to see myself here rather than there ... now rather than then".
― Blaise Pascal
|
|
|
|
|
|
I want to implement user access rights at the field level. This is what I've come up with so far. It works well but I have one drawback:
Code Behind
public partial class MainWindow : Window, INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private Dictionary<string, bool> _Rights;
public Dictionary<string, bool> Rights
{
get { return _Rights; }
set
{
if (_Rights != value)
{
_Rights = value;
RaisePropertyChanged("Rights");
}
}
}
private double _CreditLimit;
public double CreditLimit
{
get { return _CreditLimit; }
set
{
if (_CreditLimit != value)
{
_CreditLimit = value;
RaisePropertyChanged("CreditLimit");
}
}
}
public MainWindow()
{
InitializeComponent();
this.DataContext = this;
CreditLimit = 125000;
Rights = new Dictionary<string, bool>();
Rights.Add("creditLimit", false);
}
private void RaisePropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
XAML
<TextBox Text="{Binding CreditLimit, Mode=TwoWay}"
IsEnabled="{Binding Rights[creditLimit]}"
Width="100"
HorizontalAlignment="Left"
Margin="10"/>
The rights, and therefore access to the field, could be changed at runtime by simply doing
Rights["creditLimit"] = true;
RaisePropertyChanged("Rights");
The only drawback is that you really can't run any logic, meaning run specific code to determine if a textbox can be enabled. For example, the requirements for enabling the Credit Limit field might be
- The user has rights to modify the credit limit
- The customer is in good standing (their credit is still good)
- The customer does not have a balance
In this case I would not only want to check the rights list, but also some conditions on the Customer model. Where would this code go?
It is possible to somehow run a method on the VM from the IsEnabled property in the XAML?
I could try to use a multiinding but this puts the business logic in the XAML and would be messy and hard to maintain.
If it's not broken, fix it until it is.
Everything makes sense in someone's mind.
Ya can't fix stupid.
|
|
|
|
|
Access is at the "transaction level"; not "field".
Create specific "functions" (with UI) to accomplish what you want; even if it means "duplicating" a screen and making some "fields" read-only for that case.
"(I) am amazed to see myself here rather than there ... now rather than then".
― Blaise Pascal
|
|
|
|
|
Gerry Schmitz wrote: Access is at the "transaction level"; not "field".
Not sure what that means. This is why there's an IsEnabled property on the UI elements... to enable or disable them.
Gerry Schmitz wrote: Create specific "functions" (with UI) to accomplish what you want;
That 'function' is a method on the VM.
Gerry Schmitz wrote: even if it means "duplicating" a screen and making some "fields" read-only for that case.
That's rediculous. That would results in THOUSANDS of views to accomadate all possible configurations.
This seems like a solution except in their example they have the method paramaters hard coded. I would need to pass a string along. I could set the Tag on each element and use that.
If it's not broken, fix it until it is.
Everything makes sense in someone's mind.
Ya can't fix stupid.
|
|
|
|
|
It's a "pattern"; "Enabling" controls in a ui (for a given transaction) is part of that pattern.
The "function" would correspond to a "menu item"; "step"; etc. Nothing to do with "methods in code" from a "UI POV".
"Change credit limit" is not one of "thousands". It could simply be a tab, group box, etc that is "enabled or disabled". A "transaction code" could be passed to a constructor. Other fields disabled ... if it doesn't confuse. That's what governs a "copy" ... not "thousands".
Use some imagination.
"(I) am amazed to see myself here rather than there ... now rather than then".
― Blaise Pascal
|
|
|
|
|
Maybe you're not understanding what I'm trying to accomplish here.
When a user logs in their rights are retrieved and stored on a static class in a Dictionary. See below
public static class AppCore
{
public static Dictionary<string, bool> Rights { get; set; }
public static void Login(string userName, string password)
{
CurrentUser.Rights.ForEach(x => Rights.Add(x));
}
public static bool HasAccess(string itemName)
{
return Rights.Where(x => x.Key == itemName).Select(x => x.Value).FirstOrDefault();
}
}
What I want to do now is call HasAccess from the XAML. All I should have to do is set the key ("CanEditCustomer" or "CustomerCreditLimit"), or maybe the element name, on the UI element.
I have this working already with simply binding to the dictionary and setting the key, as in my original posting... What I'd really like is instead of binding to a property, I want call a method on the VM so I can do advanced logic.
If it's not broken, fix it until it is.
Everything makes sense in someone's mind.
Ya can't fix stupid.
modified 18-Apr-18 15:01pm.
|
|
|
|
|
Add, change, delete are all "functions".
To say a user "cannot" is redundant; you can simple add a rule to the user that says "can add customer".
At run time, the "ui" can access the "rule" for a given user and transaction, and enabled / disable that "menu item", tab, groupbox etc.
In most cases, the user never gets past the menu based on a rule. And which is friendlier than totally removing a menu item. In your case, if you want to enabled / disable add / edit / replace buttons, you need to establish "intent" first; which transates to less code but a few more menu items (to pass transaction codes).
Your "logging" gets more useable data too.
"(I) am amazed to see myself here rather than there ... now rather than then".
― Blaise Pascal
|
|
|
|
|
We use groups and check on view load but the principle should be the same. We have bool properties for each field that needs controlling - this can be bloody tedious even if you can group fields.
Any event bound to the VM property change can then fire the SetViewState method that checks the state of the bound object and sets the various field bools according to the rules defined.
Caveat this can become a bloody nightmare when you have hundreds of input fields that all need validating based on the user profile and the inputs. Trying to keep it simple can be a nightmare.
Never underestimate the power of human stupidity
RAH
|
|
|
|
|
Where can I find a C# equivalent (code) for the WPF, Microsoft-hidden Application.Run method?
|
|
|
|
|
|
That web page does not have the C# code equivalent of WPF's Application.Run() method. i.e., with a loop with GetMessage, DispatchMessage, etc.
modified 17-Apr-18 12:33pm.
|
|
|
|
|
As far as I can see it is the same, the difference being that it starts a Windows.Forms application, rather than a WPF one. You need to give more details of your actual problem.
|
|
|
|
|
The present WPF equivalent of what used to be:
BOOL bRet;
while( (bRet = GetMessage( &msg, hWnd, 0, 0 )) != 0)
{
if (bRet == -1)
{
}
else
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
|
|
|
|
|
That is Win32, not .NET, and the .NET equivalent is handled inside the framework.
|
|
|
|
|
That is,
public class Application {
private void Run() {
}
}
|
|
|
|
|
GregJ7 wrote: You would have to ask Microsoft. Or buy an MSDN developer subscription which gives you access to their source code.
|
|
|
|
|
Reference Source[^]
public int Run()
{
EventTrace.EasyTraceEvent(EventTrace.Keyword.KeywordGeneral | EventTrace.Keyword.KeywordPerf, EventTrace.Event.WClientAppRun);
return this.Run(null);
}
public int Run(Window window)
{
VerifyAccess();
if (InBrowserHostedApp())
{
throw new InvalidOperationException(SR.Get(SRID.CannotCallRunFromBrowserHostedApp));
}
else
{
return RunInternal(window);
}
}
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|