|
|
|
I resolved this using one of the workarounds you linked:
<TextBlock Grid.Row="2"
Grid.Column="0"
Text="Emails"
Margin="5,10,5,5"/>
<ctrls:DropDownEntryView Grid.Row="3"
Grid.Column="0"
Grid.ColumnSpan="2"
ItemCategoryKey="email_types"
HorizontalAlignment="Stretch"
Items="{Binding DataContext.EmailItems, ElementName=clientsView}"
ShowEditBar="True"
EditBarCaption="Edit Emails"
Width="400"
Margin="5">
<pre>
<i:Interaction.Triggers>
<i:EventTrigger EventName="ItemChanged" >
<cls:InvokeDelegateCommandAction Command="{Binding DataContext.EmailItemChangedCommand, ElementName=clientsView}"
CommandParameter="{Binding RelativeSource={RelativeSource Self}, Path=InvokeParameter}" />
</i:EventTrigger>
</i:Interaction.Triggers>
If it's not broken, fix it until it is.
Everything makes sense in someone's mind.
Ya can't fix stupid.
|
|
|
|
|
I have a small program, because I'm new, my program is to bring data from sql sever to textbox via combobox option and use the value shown in that textbox to calculate the + I have made it to the step of putting up the data, now thanks to you to help me with the value calculation in the textbox, thank you for your help.
xaml code :
<Window.Resources>
<local:SimpleMath x:Key="MyFriends"/>
</Window.Resources>
<Grid>
<Label Content="code" HorizontalAlignment="Left" Margin="38,52,0,0"
VerticalAlignment="Top" Width="46" Height="23"/>
<Label Content="pieces" HorizontalAlignment="Left" Margin="38,126,0,0"
VerticalAlignment="Top" Width="46" Height="23"/>
<Label Content="layers" HorizontalAlignment="Left" Margin="38,196,0,0"
VerticalAlignment="Top" Width="46" Height="30"/>
<Label Content="production pieces" HorizontalAlignment="Left"
Margin="0,278,0,0" VerticalAlignment="Top" Width="108" Height="25"/>
<TextBox x:Name="txtcode"
Text="{Binding Txtcode, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
HorizontalAlignment="Left" Height="23" Margin="124,52,0,0"
TextWrapping="Wrap" VerticalAlignment="Top" Width="141"/>
<TextBox x:Name="txtpieces"
Text="{Binding Txtpieces, Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"
HorizontalAlignment="Left" Height="23"
Margin="124,133,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="141"/>
<TextBox x:Name="txtlayers"
Text="{Binding Txtlayers,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"
HorizontalAlignment="Left" Height="23"
Margin="124,203,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="141"/>
<TextBox x:Name="txtproductionpieces"
Text="{Binding Txtproductionpieces,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"
HorizontalAlignment="Left" Height="23" Margin="124,280,0,0"
TextWrapping="Wrap" VerticalAlignment="Top" Width="141"/>
<ComboBox x:Name="comboBox1" ItemsSource="{Binding Source={StaticResource MyFriends}}"
HorizontalAlignment="Left" Margin="418,52,0,0" VerticalAlignment="Top"
Width="319" Height="36" SelectionChanged="ComboBox1_SelectionChanged"/>
<TextBox x:Name="txtseccond"
Text="{Binding Txtseccond,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"
HorizontalAlignment="Left" Height="23"
Margin="124,345,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="141"/>
<Label Content="seccond" HorizontalAlignment="Left" Margin="38,345,0,0"
VerticalAlignment="Top" Width="46" Height="23"/>
<TextBlock Text="{Binding A, Mode=OneWay,UpdateSourceTrigger=PropertyChanged}"
HorizontalAlignment="Left" Margin="418,133,0,0" TextWrapping="Wrap"
VerticalAlignment="Top" Height="23" Width="248"/>
<TextBox Text="{Binding No1,Mode=OneWay,UpdateSourceTrigger=PropertyChanged}"
HorizontalAlignment="Left" Height="21" Margin="426,210,0,0"
TextWrapping="Wrap" VerticalAlignment="Top" Width="303"/>
</Grid>
</Window>
C# code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Data.SqlClient;
using System.ComponentModel;
using System.Runtime.CompilerServices;
namespace comboboxapp1
{
///
/// Interaction logic for MainWindow.xaml
///
public partial class MainWindow : Window
{
public SimpleMath Formular { get; set; }
public object SelectedValue { get; private set; }
public MainWindow()
{
Formular = new SimpleMath()
{
Txtcode = 0,
Txtpieces = 0,
Txtlayers = 0,
Txtproductionpieces = 0,
Txtseccond = 0,
};
InitializeComponent();
DataContext = Formular;
Fillcombobox();
}
private void MainWindow_Load(object sender, EventArgs e)
{
}
public void Fillcombobox()
{
SqlConnection con = new SqlConnection("Data Source=LEAN-22\\SQLEXPRESS;Initial
Catalog=LUAT;Integrated Security=True");
string sql = " select * from comboboxnew ";
SqlCommand cmd = new SqlCommand(sql, con);
SqlDataReader myreader;
try
{
con.Open();
myreader = cmd.ExecuteReader();
while (myreader.Read())
{
string sname = myreader.GetInt32(0).ToString();
comboBox1.Items.Add(sname);
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
public class SimpleMath : INotifyPropertyChanged
{
private int no1;
public int No1
{
get { return no1; }
set
{
no1 = value;
OnPropertyChanged("No1");
OnPropertyChanged("A");
}
}
private int txtcode;
public int Txtcode
{
get { return txtcode; }
set
{
txtcode = value;
OnPropertyChanged("Txtcode");
OnPropertyChanged("A");
}
}
private int txtpieces;
public int Txtpieces
{
get { return txtpieces; }
set
{
txtpieces = value;
OnPropertyChanged("Txtcode");
OnPropertyChanged("A");
}
}
private int txtlayers;
public int Txtlayers
{
get { return txtlayers; }
set
{
txtlayers = value;
OnPropertyChanged("Txtlayers");
OnPropertyChanged("A");
}
}
private int txtproductionpieces;
public int Txtproductionpieces
{
get { return txtproductionpieces; }
set
{
txtproductionpieces = value;
OnPropertyChanged("Txtproductionpieces");
OnPropertyChanged("A");
}
}
private int txtseccond;
public int Txtseccond
{
get { return txtseccond; }
set
{
txtseccond = value;
OnPropertyChanged("Txtseccond");
OnPropertyChanged("A");
}
}
public double A => No1;
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged([CallerMemberName()] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
private void ComboBox1_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
SqlConnection con = new SqlConnection("Data Source=LEAN-22\\SQLEXPRESS;Initial
Catalog=LUAT;Integrated Security=True");
// string sql = " select * from comboboxnew where code = '" + comboBox1.Text+ "';";
string sql = " select * from comboboxnew where code = '" + comboBox1.SelectedItem +
"';";
//Console.WriteLine(comboBox1.Text);
//MessageBox.Show(comboBox1.Text);
SqlCommand cmd = new SqlCommand(sql, con);
SqlDataReader myreader;
try
{
con.Open();
myreader = cmd.ExecuteReader();
while (myreader.Read())
{
string code = myreader.GetInt32(0).ToString();
string pieces = myreader.GetInt32(1).ToString();
string layers = myreader.GetInt32(2).ToString();
string productionpieces = myreader.GetInt32(3).ToString();
string seccond = myreader.GetInt32(4).ToString();
txtcode.Text = code;
//txtcode.Text =SelectedValue;
txtpieces.Text = pieces;
//txtpieces.Text = "New value";
txtlayers.Text = layers;
//txtlayers.Text = "New value";
txtproductionpieces.Text = productionpieces;
//txtproductionpieces.Text = "New value";
txtseccond.Text = seccond;
//txtseccond.Text = "New value";
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
}
}
|
|
|
|
|
What is the problem, and where does it occur?
|
|
|
|
|
|
Member 14680372 wrote:
string sql = " select * from comboboxnew where code = '" + comboBox1.SelectedItem + "';"; Don't do it like that!
Your code is vulnerable to SQL Injection[^]. NEVER use string concatenation to build a SQL query. ALWAYS use a parameterized query.
Everything you wanted to know about SQL injection (but were afraid to ask) | Troy Hunt[^]
How can I explain SQL injection without technical jargon? | Information Security Stack Exchange[^]
Query Parameterization Cheat Sheet | OWASP[^]
private void ComboBox1_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
using (SqlConnection con = new SqlConnection("Data Source=LEAN-22\\SQLEXPRESS;Initial Catalog=LUAT;Integrated Security=True"))
using (SqlCommand cmd = new SqlCommand("SELECT TOP 1 * FROM comboboxnew WHERE code = @code;"))
{
cmd.Parameters.AddWithValue("@code", Convert.ToString(comboBox1.SelectedItem));
con.Open();
using (SqlDataReader myreader = cmd.ExecuteReader(CommandBehavior.CloseConnection))
{
if (myreader.Read())
{
string code = myreader.GetInt32(0).ToString();
string pieces = myreader.GetInt32(1).ToString();
string layers = myreader.GetInt32(2).ToString();
string productionpieces = myreader.GetInt32(3).ToString();
string seccond = myreader.GetInt32(4).ToString();
txtcode.Text = code;
txtpieces.Text = pieces;
txtlayers.Text = layers;
txtproductionpieces.Text = productionpieces;
txtseccond.Text = seccond;
}
}
}
} NB: You should avoid using SELECT * FROM ... ; instead, specify the exact list of fields you want to load.
You'll need to check that Convert.ToString(comboBox1.SelectedItem) returns the value you're expecting. If it's a data-bound list, it might return something like "System.Data.DataRowView" instead, in which case you'll need to do some more work to get the real value.
And you should avoid hard-coding your connection strings. Store them in a configuration file instead. For example:
How to: Read Connection Strings from the Web.config File | Microsoft Docs[^]
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
I created an AttachedProperty to handle enabling/disable UI elements based on a user's access rights:
public static class UIElementEnablerExtension
{
public static string GetSecurityKey(DependencyObject obj)
{
return (string)obj.GetValue(SecurityKeyProperty);
}
public static void SetSecurityKey(DependencyObject obj, string value)
{
obj.SetValue(SecurityKeyProperty, value);
}
public static readonly DependencyProperty SecurityKeyProperty =
DependencyProperty.RegisterAttached(
"SecurityKey", typeof(string), typeof(UIElementEnablerExtension),
new UIPropertyMetadata("", OnSecurityKeyPropertyChanged));
private static void OnSecurityKeyPropertyChanged(DependencyObject d,DependencyPropertyChangedEventArgs e)
{
if (AppCore.CurrentUser != null)
{
var accessKey = (string)e.NewValue;
if (!string.IsNullOrEmpty(accessKey))
{
var element = (UIElement)d;
var hasAccess = AppCore.CurrentUser.Rights.Any(x => x.CompareTo(accessKey) == 0);
element.IsEnabled = hasAccess;
}
}
}
}
Usage
<Button Content="Can Do Something"
Command="{Binding MyCommand"}
cls:UIElementEnablerExtension.SecurityKey="canUpdate"/>
The problem is that this fires long before the user is prompted to login. how cann I refresh this, or fire it again AFTER the user has logged in?
Or, does anyone have a better approach?
If it's not broken, fix it until it is.
Everything makes sense in someone's mind.
Ya can't fix stupid.
modified 7-Jan-20 16:59pm.
|
|
|
|
|
As far as I can see, there isn't a way to get a list of elements with a particular attached property set. I suspect you'll need to maintain your own list, using the WeakReference<T> class[^] to avoid a memory leak.
Perhaps something like this?
public static class UIElementEnablerExtension
{
private static readonly ReaderWriterLockSlim Locker = new ReaderWriterLockSlim();
private static readonly List<WeakReference<UIElement>> TrackedElements = new List<WeakReference<UIElement>>();
public static readonly DependencyProperty SecurityKeyProperty = DependencyProperty.RegisterAttached(
"SecurityKey", typeof(string), typeof(UIElementEnablerExtension),
new UIPropertyMetadata("", OnSecurityKeyPropertyChanged));
public static string GetSecurityKey(DependencyObject obj) => (string)obj.GetValue(SecurityKeyProperty);
public static void SetSecurityKey(DependencyObject obj, string value) => obj.SetValue(SecurityKeyProperty);
private static void OnSecurityKeyPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (d is UIElement element)
{
Locker.EnterWriteLock();
try
{
TrackedElements.Add(new WeakReference<UIElement>(element));
}
finally
{
Locker.ExitWriteLock();
}
EnableOrDisableElement(element);
}
}
public static void OnCurrentUserChanged()
{
List<WeakReference<UIElement>> elements;
Locker.EntryReadLock();
try
{
elements = new List<WeakReference<UIElement>>(TrackedElements.Count);
elements.AddRange(TrackedElements);
}
finally
{
Locker.ExitReadLock();
}
var elementsToRemove = new List<WeakReference<UIElement>>();
foreach (WeakReference<UIElement> item in elements)
{
if (item.TryGetTarget(out UIElement element))
{
EnableOrDisableElement(element);
}
else
{
elementsToRemove.Add(item);
}
}
if (elementsToRemove.Count != 0)
{
Locker.EnterWriteLock();
try
{
foreach (WeakReference<UIElement> item in elementsToRemove)
{
TrackedElements.Remove(item);
}
}
finally
{
Locker.ExitWriteLock();
}
}
}
private static void EnableOrDisableElement(UIElement element)
{
string accessKey = GetSecurityKey(element);
if (string.IsNullOrEmpty(accessKey))
{
element.IsEnabled = true;
return;
}
bool hasAccess = AppCore.CurrentUser?.Rights.Any(x => string.Equals(x, accessKey, StringComparison.Ordinal)) ?? false;
element.IsEnabled = hasAccess;
}
} You'll need to call UIElementEnablerExtension.OnCurrentUserChanged when the user logs in, either directly or using a mediator.
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
I have an Exception Window dialog that I pop up when an error occurs. On it is a "Send Error Report" button that opens an email. I wrote out the Exception.ToString() to a file and attached it to the email.
I feel like this isn't enough info to accurately debug. So the question is, what else would you send?
If it's not broken, fix it until it is.
Everything makes sense in someone's mind.
Ya can't fix stupid.
|
|
|
|
|
Kevin Marois wrote: what else would you send? Stack trace, source code around the place that caused the exception, assuming you can capture such information. Really it is up to you to decide what information you would need in order to diagnose what went wrong.
|
|
|
|
|
Exception.ToString() doesn't usually give you the full picture. I usually recursively access the InnerException property and on each Exception level write down the exception type, message and stacktrace.
|
|
|
|
|
If the issue involved a "class", as in say a WCF message API, I would serialize the class to XML and include that also in the report (besides the stack trace, recursive inner exceptions, etc.)
Also: user id, machine name, OS, date and time, app version / file dates.
It was only in wine that he laid down no limit for himself, but he did not allow himself to be confused by it.
― Confucian Analects: Rules of Confucius about his food
|
|
|
|
|
I send the stack trace and the method name as well as the error message.
Never underestimate the power of human stupidity -
RAH
I'm old. I know stuff - JSOP
|
|
|
|
|
I have a MenuButton on my Main Window toolbar:
<menubtn:DropDownButton Grid.Column="2"
x:Name="btnAddItem"
ToolTip="New Item"
Margin="2">
<pre>
<Image Height="32"
Width="32"
Source="/Jayhawk.UI.WPF;component/Media/Images/new.png"/>
<menubtn:DropDownButton.Menu>
<ContextMenu>
<MenuItem x:Name="newCompanyButton"
Command="{Binding NewItemCommand}"
CommandParameter="{Binding RelativeSource={RelativeSource Self}}"
Tag="company"
Header="New Company" />
<MenuItem x:Name="newProjectButton"
Command="{Binding NewItemCommand}"
CommandParameter="{Binding RelativeSource={RelativeSource Self}}"
Tag="project"
Header="New Project" />
<MenuItem x:Name="newEmployeeButton"
Command="{Binding NewItemCommand}"
CommandParameter="{Binding RelativeSource={RelativeSource Self}}"
Tag="employee"
Header="New Employee" />
</ContextMenu>
</menubtn:DropDownButton.Menu>
Here's the DropDown button code:
public class DropDownButton : ToggleButton
{
public DropDownButton()
{
Binding binding = new Binding("Menu.IsOpen");
binding.Source = this;
this.SetBinding(IsCheckedProperty, binding);
DataContextChanged += (sender, args) =>
{
if (Menu != null)
Menu.DataContext = DataContext;
};
}
public ContextMenu Menu
{
get { return (ContextMenu)GetValue(MenuProperty); }
set { SetValue(MenuProperty, value); }
}
public static readonly DependencyProperty MenuProperty = DependencyProperty.Register("Menu", typeof(ContextMenu), typeof(DropDownButton), new UIPropertyMetadata(null, OnMenuChanged));
private static void OnMenuChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var dropDownButton = (DropDownButton)d;
var contextMenu = (ContextMenu)e.NewValue;
contextMenu.DataContext = dropDownButton.DataContext;
}
protected override void OnClick()
{
if (Menu != null)
{
Menu.PlacementTarget = this;
Menu.Placement = PlacementMode.Bottom;
Menu.IsOpen = true;
}
}
}
Here's the VM code:
private ICommand _NewItemCommand;
public ICommand NewItemCommand
{
get
{
if (_NewItemCommand == null)
_NewItemCommand = new RelayCommand<object>(p => NewItemExecuted(p), p => NewItemCanExecute());
return _NewItemCommand;
}
}
and
private bool NewItemCanExecute()
{
bool canExecute = true;
if (SelectedTabView != null)
{
switch (SelectedTabView.ItemType)
{
case NavigationItemType.Employee:
canExecute = AppCore.AppSecurity.HasAccess("add_employees");
break;
default:
break;
}
}
return canExecute;
}
The problem is that the CanExecute doesn't fire until I actually click on a menu bar.
If it's not broken, fix it until it is.
Everything makes sense in someone's mind.
Ya can't fix stupid.
|
|
|
|
|
And that's why I use user controls and "code-behind". Ship now or ship maybe.
Why a "binding" instead of just a menu command parameter "constant" or "enum"? How many ways can you "add a company"?
It was only in wine that he laid down no limit for himself, but he did not allow himself to be confused by it.
― Confucian Analects: Rules of Confucius about his food
|
|
|
|
|
Gerry Schmitz wrote: And that's why I use user controls and "code-behind". Ship now or ship maybe.
Not sure what that means
Gerry Schmitz wrote: Why a "binding" instead of just a menu command parameter "constant" or "enum"? How many ways can you "add a company"?
Binding? As opposed to....?
Not sure what this response means. How else would this be done? I'm using a command that bound to the menu bars.
If I understand what you're asking, I decided to use one command for all menu bars. This way I don't have to have a command and Execute/CanExecute for each bar.
If it's not broken, fix it until it is.
Everything makes sense in someone's mind.
Ya can't fix stupid.
|
|
|
|
|
For example:
<MenuItem x:Name="newCompanyButton"
Command="{Binding NewItemCommand}"
CommandParameter="{Binding RelativeSource={RelativeSource Self}}"
CommandParameter="{x:Static local:ActionId.NewCompany}"
Tag="company"
Header="New Company" />
And "Tag" is your parameter. How many do you need?
Or, menu click "sender" identifies the menu item.
Your could even examine the "header"; or the "Name".
A lot of "binding" for nothing, and only confusing for the next person.
It was only in wine that he laid down no limit for himself, but he did not allow himself to be confused by it.
― Confucian Analects: Rules of Confucius about his food
|
|
|
|
|
Why not pass the "tag" value as a commandparameter?
Seems to me you should be using the enabled property when constructing the menu to manage access via the app security not the canexecute which logically only fires when the item is clicked!
Never underestimate the power of human stupidity -
RAH
I'm old. I know stuff - JSOP
|
|
|
|
|
Can execute fires alot, like when the window refreshes. I want the b as r disabled BEFORE the user can click on it
If it's not broken, fix it until it is.
Everything makes sense in someone's mind.
Ya can't fix stupid.
|
|
|
|
|
Your canexecute defines if the user can execute the menu item based on the users security profile (or am I missing something), why are you not disabling the menu item when you construct the menu, or don't even add the item if the user does not have permissions.
Never underestimate the power of human stupidity -
RAH
I'm old. I know stuff - JSOP
|
|
|
|
|
Constructing the menu happens once. The security profile can change at runtime, for example, the admin can grant access.
I could force the user to log out and back in, but then I'd have to rebuild the UI to enable/disable things in response
If it's not broken, fix it until it is.
Everything makes sense in someone's mind.
Ya can't fix stupid.
|
|
|
|
|
Kevin Marois wrote: The security profile can change at runtime, for example, the admin can grant access. I have supplied a function to refresh/change the user profile from the main landing page (mainwindow) without having to log off. I always use the constructor and disable items. So I'm no use to you with the CanExecute issue.
Kevin Marois wrote: I'd have to rebuild the UI to enable/disable things in response Now that on the other hand would be irritating.
Never underestimate the power of human stupidity -
RAH
I'm old. I know stuff - JSOP
|
|
|
|
|
Kevin Marois wrote: The problem is that the CanExecute doesn't fire until I actually click on a menu bar.
As far as I can see, that would be the expected behaviour. The system doesn't need to know whether the menu item is enabled or not until the menu is shown, so I wouldn't expect it to call CanExecute for the menu's command until you click on the button to show the menu.
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
In wpf mvvm, a checkbox is set in a custom popup. If there is another datagrid below the popup control, clicking the checkbox will pass the mouse click event to the lower layer. How to control the mouse click event in the custom popup at the upper layer, so that the click event is not passed to the bottom layer, thank you
|
|
|
|
|