I have an ASPxComboBox which I was able to get filtering correctly on user input. Now I want to save the selected item to the database. But when I try to get the SelectedItem it is null.
ASP
<dxe:ASPxComboBox ID="cboInstructor" runat="server" Width="100%"
EnableCallbackMode="True" CallbackPageSize="10"
IncrementalFilteringMode="Contains" ValueType="System.Int32" ValueField="employee_id"
OnItemsRequestedByFilterCondition="cboInstructor_OnItemsRequestedByFilterCondition_SQL"
OnItemRequestedByValue="cboInstructor_OnItemRequestedByValue_SQL" TextFormatString="{0} {1}"
DropDownStyle="DropDown"
>
<Columns>
<dxe:ListBoxColumn FieldName="display_forename" Caption="Forename" />
<dxe:ListBoxColumn FieldName="display_surname" Caption="Surname" />
</Columns>
</dxe:ASPxComboBox>
<asp:SqlDataSource ID="SqlDataSourceInstruct" runat="server" ConnectionString="Server=testserver;User ID=root;Password=password;Persist Security Info=True;Database=central" ProviderName="MySql.Data.MySqlClient" SelectCommand="GetUser" SelectCommandType="StoredProcedure">
<SelectParameters>
<asp:Parameter Name="filter" Type="String" />
<asp:Parameter Name="startIndex" Type="Int32" />
<asp:Parameter Name="endIndex" Type="Int32" />
</SelectParameters>
</asp:SqlDataSource>
<asp:SqlDataSource ID="SqlDataSourceInstructPopulate" runat="server" ConnectionString="Server=testserver;User ID=root;Password=password;Persist Security Info=True;Database=central" ProviderName="MySql.Data.MySqlClient" SelectCommand="GetUser" SelectCommandType="StoredProcedure">
</asp:SqlDataSource>
<asp:Button ID="btnTest" runat="server" Text="Test" OnClick="btnTest_Click" />
CS
protected void Page_Load(object sender, EventArgs e)
{
}
protected void cboInstructor_OnItemsRequestedByFilterCondition_SQL(object source, ListEditItemsRequestedByFilterConditionEventArgs e)
{
ASPxComboBox comboBox = (ASPxComboBox)source;
SqlDataSourceInstruct.SelectParameters.Clear();
SqlDataSourceInstruct.SelectParameters.Add("filter", TypeCode.String, string.Format("%{0}%", e.Filter));
SqlDataSourceInstruct.SelectParameters.Add("startIndex", TypeCode.Int32, (e.BeginIndex + 1).ToString());
SqlDataSourceInstruct.SelectParameters.Add("endIndex", TypeCode.Int32, (e.EndIndex + 1).ToString());
comboBox.DataSource = SqlDataSourceInstruct;
comboBox.DataBind();
}
protected void cboInstructor_OnItemRequestedByValue_SQL(object source, ListEditItemRequestedByValueEventArgs e)
{
long value = 0;
if (e.Value == null)
return;
if (!Int64.TryParse(e.Value.ToString(), out value))
return;
ASPxComboBox comboBox = (ASPxComboBox)source;
SqlDataSourceInstructPopulate.SelectCommand = #"SELECT employee_id, display_surname, display_forename FROM user_record WHERE employee_id = #ID ORDER BY display_forename";
SqlDataSourceInstructPopulate.SelectCommandType = System.Web.UI.WebControls.SqlDataSourceCommandType.Text;
SqlDataSourceInstructPopulate.SelectParameters.Clear();
SqlDataSourceInstructPopulate.SelectParameters.Add("ID", TypeCode.Int64, e.Value.ToString());
comboBox.DataSource = SqlDataSourceInstructPopulate;
comboBox.DataBind();
comboBox.ValueField = "employee_id";
}
protected void btnTest_Click(object sender, EventArgs e)
{
int iTest = (int)cboInstructor.SelectedItem.GetValue("employee_id");
}
At the line:
int iTest = (int)cboInstructor.SelectedItem.GetValue("employee_id");
cboInstructor.SelectedItem is null. Anyone have an idea why?
Anthony,
The SelectedItem is used to specify the item to select. Once an item is selected in the ASPxComboBox, you can use the Value or Text property to reference it.
http://documentation.devexpress.com/#AspNet/DevExpressWebASPxEditorsASPxComboBoxMembersTopicAll
This thread may also help you:
http://community.devexpress.com/forums/t/61424.aspx
Thanks.
I know this question is old, but in case someone is looking through it. Here are other possible solutions:
Make sure the ValueType matches the actual 'Value' type as per your table. Some Value types are not populated automatically, like "System.Guid". But they are available. Essentially DevExpress will use any value type your table is using, even if it's not listed, if you type it manually, it will pick it up.
By design, the ASPxComboBox does not synchronize to the server-side. To fix this, always bind your ASPxComboBox at every page request. So essentially your page load would look like this
protected void Page_Load(object sender, EventArgs e)
{
SqlDataSourceInstruct.SelectParameters.Clear();
SqlDataSourceInstruct.SelectParameters.Add("filter",TypeCode.String, string.Format("%{0}%", e.Filter));
SqlDataSourceInstruct.SelectParameters.Add("startIndex", TypeCode.Int32, (e.BeginIndex + 1).ToString());
SqlDataSourceInstruct.SelectParameters.Add("endIndex", TypeCode.Int32, (e.EndIndex + 1).ToString());
cboInstructor.DataSource = SqlDataSourceInstruct;
cboInstructor.DataBind();
}
Ideally you would have a method that reloads your ASPxComboBox and you would just call that method instead of repeating this code everytime
Related
I have my grid panel as follows
<ext:GridPanel ID="GridPanel1" runat="server" Height="300" Title="Title">
<ColumnModel runat="server">
<Columns>
</Columns>
</ColumnModel>
<Store>
<ext:Store ID="Store1" runat="server" EnableViewState="true">
</ext:Store>
</Store>
<SelectionModel>
<ext:RowSelectionModel ID="RowSelectionModel1" SingleSelect="true" runat="server">
</ext:RowSelectionModel>
</SelectionModel>
<Buttons>
<ext:Button ID="btnDelete" runat="server" Text="Delete">
<DirectEvents>
<Click OnEvent="Delete">
<ExtraParams>
<ext:Parameter Name="Values" Value="Ext.encode(#{GridPanel1}.getRowsValues({selectedOnly:true}))"
Mode="Raw" />
</ExtraParams>
</Click>
</DirectEvents>
</ext:Button>
</Buttons>
</ext:GridPanel>
This is my grid from my database
This is my code to delete the selected row but this is looping for row value as i used dictionary
protected void Delete(object sender, DirectEventArgs e)
{
string json = e.ExtraParams["Values"];
string value = string.Empty;
Dictionary<string, string>[] companies = JSON.Deserialize<Dictionary<string, string>[]>(json);
bool addHeader = true;
foreach (Dictionary<string, string> row in companies)
{
if (addHeader)
{
//sb.Append("<tr>");
foreach (KeyValuePair<string, string> keyValuePair in row)
{
value = keyValuePair.Value.ToString();
SqlConnection con = new SqlConnection(connection);
con.Open();
SqlCommand cmd = new SqlCommand("Delete from Users where Name='" + value + "'", con);
cmd.ExecuteNonQuery();
BindData();
}
addHeader = false;
}
}
}
If I select first row and click on delete I would like to delete that row and Bind grid again. Can any one tell how to do this. Also I would like to alert a message box if the user didn't select any row using Java script
Is this ExtJs4? Look for getSelectionModel().getSelection() method of your grid control.
Is it possible to determine whether a Selector.SelectionChanged event was initiated by the user or programmatically?
I.e. I need something like a boolean "IsUserInitiated" property that is true only if the SelectionChanged event was raised because the user changed the selection using mouse or keyboard.
Simple work around:
You could create a method that temporarily disables the SelectionChanged event and call it when you need to change the selection programmatically.
private void SelectGridRow( int SelectedIndex )
{
myDataGrid.SelectionChanged -= myDataGrid_SelectionChanged;
myDataGrid.SelectedIndex = SelectedIndex;
// other work ...
myDataGrid.SelectionChanged += myDataGrid_SelectionChanged;
}
This should work in most scenarios:
private void cboStatus_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (this.cboStatus.IsDropDownOpen)
{
//OPTIONAL:
//Causes the combobox selection changed to not be fired again if anything
//in the function below changes the selection (as in my weird case)
this.cboStatus.IsDropDownOpen = false;
//now put the code you want to fire when a user selects an option here
}
}
This is a problem I have had to work around since WinForms. I was hoping that in WPF they would add a boolean to SelectionChangedEventArgs called something like IsUserInitiated as mentioned in the question. I have most commonly needed this when I want to ignore anything happening while the data is loading and binding to the screen. For example, say I am defaulting a field based on the new value in SelectionChanged BUT I want the user to be able to overwrite this default value, and I only want the user to overwrite it, NOT the application when the screen reloads. I still feel like what I have been doing is hacky, but I will post it because I don't see it mentioned. No fancy tricks, just simple and effective.
1) Create a class level boolean called _loading
private bool _loading;
2) Update the boolean in the method doing the loading
private async Task Load()
{
_loading = true;
//load some stuff
_loading = false;
}
3) Use the boolean whenever you need to
private void SetDefaultValue(object sender, SelectionChangedEventArgs e)
{
if (!_loading) {
//set a default value
}
}
Taken from http://social.msdn.microsoft.com where the user post the same question
I don't think we can distinguish whether a SelectionChanged event was initiated by the user input or programmatically. SelectionChanged event doesn't care that.
Generally, you can always now whether it is initiated programmatically because it's your code that initiates it.
If you use DataBinding to bind the SelectedItem, you can set the NotifyOnSourceUpdated and NotifyOnTargetUpdated properties to True. And you can handle the Binding.SourceUpdated and Binding.TargetUpdated events. In most cases, the change initiated by the user inputs goes from Target to Source. If the change is initiated programmatically, it goes from Source to Target.
I don't know if it can help...
You could use an custom routed event and hook up the appropriate handlers in an behavior like this:
public class UserSelectionChangedEventArgs : RoutedEventArgs
{
public UserSelectionChangedEventArgs( RoutedEvent id, SelectionChangedEventArgs args , bool changedByUser) :base(id)
{
SelectionChangedByUser = changedByUser;
RemovedItems = args.RemovedItems;
AddedItems = args.AddedItems;
}
public bool SelectionChangedByUser { get; set; }
public IList RemovedItems { get; set; }
public IList AddedItems { get; set; }
}
public delegate void UserSelectionChangedEventHandler( object sender, UserSelectionChangedEventArgs e );
public class UserSelectionChangedBehavior : Behavior<Selector>
{
private bool m_expectingSelectionChanged;
public static readonly RoutedEvent UserSelectionChangedEvent = EventManager.RegisterRoutedEvent( "UserSelectionChanged", RoutingStrategy.Bubble, typeof( UserSelectionChangedEventHandler ), typeof( Selector ) );
public static void AddUserSelectionChangedHandler( DependencyObject d, UserSelectionChangedEventHandler handler )
{
( (Selector) d ).AddHandler( UserSelectionChangedEvent, handler );
}
public static void RemoveUserSelectionChangedHandler( DependencyObject d, UserSelectionChangedEventHandler handler )
{
( (Selector) d ).RemoveHandler( UserSelectionChangedEvent, handler );
}
private void RaiseUserSelectionChangedEvent( UserSelectionChangedEventArgs args )
{
AssociatedObject.RaiseEvent( args );
}
protected override void OnAttached()
{
AssociatedObject.PreviewKeyDown += OnKeyDown;
AssociatedObject.PreviewKeyUp += OnKeyUp;
AssociatedObject.PreviewMouseLeftButtonDown += OnMouseLeftButtonDown;
AssociatedObject.PreviewMouseLeftButtonUp += OnMouseLeftButtonUp;
AssociatedObject.SelectionChanged += OnSelectionChanged;
base.OnAttached();
}
protected override void OnDetaching()
{
AssociatedObject.PreviewKeyDown -= OnKeyDown;
AssociatedObject.PreviewKeyUp -= OnKeyUp;
AssociatedObject.PreviewMouseLeftButtonDown -= OnMouseLeftButtonDown;
AssociatedObject.PreviewMouseLeftButtonUp -= OnMouseLeftButtonUp;
AssociatedObject.SelectionChanged -= OnSelectionChanged;
base.OnDetaching();
}
private void OnMouseLeftButtonUp( object sender, MouseButtonEventArgs e )
{
m_expectingSelectionChanged = false;
}
private void OnKeyDown( object sender, KeyEventArgs e )
{
m_expectingSelectionChanged = true;
}
private void OnKeyUp( object sender, KeyEventArgs e )
{
m_expectingSelectionChanged = false;
}
private void OnMouseLeftButtonDown( object sender, MouseButtonEventArgs e )
{
m_expectingSelectionChanged = true;
}
private void OnSelectionChanged( object sender, SelectionChangedEventArgs e )
{
RaiseUserSelectionChangedEvent( new UserSelectionChangedEventArgs( UserSelectionChangedEvent, e, m_expectingSelectionChanged ) );
}
}
In XAML you could just subscribe to the UserSelectionChangedEvent like this:
<ListBox ItemsSource="{Binding Items}" b:UserSelectionChangedBehavior.UserSelectionChanged="OnUserSelectionChanged">
<i:Interaction.Behaviors>
<b:UserSelectionChangedBehavior/>
</i:Interaction.Behaviors>
Handler:
private void OnUserSelectionChanged( object sender, UserSelectionChangedEventArgs e )
{
if(e.SelectionChangedByUser)
{
Console.WriteLine( "Selection changed by user" );
}
else
{
Console.WriteLine( "Selection changed by code" );
}
}
This is just an idea. Probably you won't even need the behavior and just define the attached routed event. But then I have no idea where to store the m_expectingSelectionChanged flag. I also don't know if this works in all cases. But maybe it gives you a starting point.
Usually a Selector has it's selection set/changed when the control is loaded into view. When this happens the IsLoaded property is still false. When a user makes a selection manually the control obviously has to be visible and hence IsLoaded will be true. Try using this property to determine if a change is user initiated or due to the control being loaded.
Why do you want to know?
I have coded many dialogs where I had similar situations - I didn't really want to know that the user used the mouse or keyboard, but I did want a specific behaviour, and I did want effects from triggering some binding to behave the right way.
For most cases I have found that using the MVVM pattern - or at least separating logic from ui - you often avoid those problems.
So for your problem I would try to eliminate the selectionchanged handler and only use bindings - so your state of the gui is based on the model behind and not the wireing of events.
mvvm:
http://en.wikipedia.org/wiki/Model_View_ViewModel
You can check for AddedItems and RemovedItems. If it was initiated by user both properties has an item. If an item was just added via code the RemovedItems list should be empty. So
if (e.AddedItems.Count>0 && e.RemovedItems.Count > 0)
//Initiated by user
I need to be able to load html page with Silverlight module presenting the content based on page was accessed from. For example, if request to open the page come from Page1.html than the content will show Content.1. I tried to work on it but need more information. Any help is highly appreciated:
Here is my code:
HTML: assigned new param:
<param name="inputParams" value="Page1.html" />
It can be a different url string.
Silverlight Code in App.xaml.cs
private void Application_Startup(object sender, StartupEventArgs e)
{
this.RootVisual = new MainPage();
if (e.InitParams != null)
{
string ValueParam = e.InitParams["value"];
}
}
MainPage.xaml.cs
public MainPage()
{
InitializeComponent();
this.Loaded += new RoutedEventHandler(MainPage_Loaded);
}
void MainPage_Loaded(object sender, RoutedEventArgs e)
{
if (ValueParam = ?)
{
contentIndex =1;
}
}
The value of the initParams parameter is itself expected to be a series comma separated of name=value pairs.
Your param element should look like this:-
<param name="inputParams" value="value=Page1.html" />
Having said that your specific requirement you can the at the host page's URL via the HtmlPage object.
string path = HtmlPage.Document.DocumentUri.AbsolutePath;
This can save you having to specifically copy the page name into each initParams for each page.
i have a field in my database for detect font syle of a row.
font syle is Regular where it is true.
I want to changing my row style when select it. i write this :
private void myGrid_SelectionChanged(object sender, EventArgs e)
{
DataBaseComponent.EditFieldofObject(object1.Serial, true);
if (myGrid.SelectedRows[0].VisualElement != null)
myGrid.SelectedRows[0].VisualElement.Font = new System.Drawing.Font("Tahoma", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(178)));
myGrid.SelectedRows[0].Cells["myField"].Value = true;
}
but it doesnot work and i must bind grid again to see this change.
Why not use ItemDataBound instead of SelectionChanged? This will work for your needs.
protected void myGrid_ItemDataBound(object sender, GridItemEventArgs e)
{
if (e.Item is GridDataItem)
{
GridDataItem dataBoundItem = (GridDataItem)e.Item;
if (dataBoundItem["ColumnName"].Text.ToString() == "True")
{
// Do something here
}
}
}
There is a good article on Telerik explaining it.
I'm trying to figure out how to cancel user input in a TextBox when a validation error occurs. If the user attempts to enter an invalid character I would like to prevent it from being added to the TextBox.
How can I add to or modify the code below to prevent the TextBox from accepting invalid characters? Is it possible without listening to the TextBox.TextChanged event?
My TextBox looks like:
<TextBox Validation.Error="OnSomeTextBoxValidationError">
<TextBox.Text>
<Binding Path="Value" NotifyOnValidationError="True" UpdateSourceTrigger="PropertyChanged">
<Binding.ValidationRules>
<local:SomeValidationRule />
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
</TextBox>
My custom validation rule looks like:
public class SomeValidationRule : ValidationRule
{
public override ValidationResult Validate(object value, CultureInfo cultureInfo)
{
string hex_string = value as string;
Match invalid_chars = Regex.Match(hex_string, "[^0-9a-fA-F]");
bool is_valid = (invalid_chars.Success == false);
string error_context = null;
if (is_valid == false)
{
error_context = "Invalid characters";
}
return new ValidationResult(is_valid, error_context);
}
}
I have an error handler... can I do anything with it?
private void OnSomeTextBoxValidationError(object sender, ValidationErrorEventArgs e)
{
// Can I do anything here?
}
Please provide an original answer if possible, rather than referring to a URL. I've read a lot of possible solutions involving event handlers, but I haven't come across anyone discussing the possibility of doing all my validation in the ValidationRule.
After a lot of research it seems that the only way to have full control over the input to a TextBox is to handle several events directly. According to WPF Recipes in C# 2008 (1st ed., p. 169):
Unfortunately, there's no easy way (at present) to combine the useful, high-level data binding feature with the lower-level keyboard handling that would be necessary to prevent the user from typing invalid characters altogether.
Here's what I came up with to create a hexadecimal numeric TextBox which only accepts characters a-f, A-F and 0-9.
SomeClass.xaml
<TextBox
x:Name="SomeTextBox"
LostFocus="TextBoxLostFocus"
PreviewKeyDown="TextBoxPreviewKeyDown"
PreviewTextInput="TextBoxPreviewTextInput" />
SomeClass.xaml.cs
private string mInvalidCharPattern = "[^0-9a-fA-F]";
// In my case SomeClass derives from UserControl
public SomeClass()
{
DataObject.AddPastingHandler(
this.SomeTextBox,
new DataObjectPastingEventHandler(TextBoxPasting));
}
private void TextBoxLostFocus(object sender, RoutedEventArgs e)
{
// You may want to refresh the TextBox's Text here. If the user deletes
// the contents of the TextBox and clicks off of it, then you can restore
// the original value.
}
// Catch the space character, since it doesn't trigger PreviewTextInput
private void TextBoxPreviewKeyDown(object sender, KeyEventArgs e)
{
if (e.Key == Key.Space) { e.Handled = true; }
}
// Do most validation here
private void TextBoxPreviewTextInput(object sender, TextCompositionEventArgs e)
{
if (ValidateTextInput(e.Text) == false) { e.Handled = true; }
}
// Prevent pasting invalid characters
private void TextBoxPasting(object sender, DataObjectPastingEventArgs e)
{
string lPastingText = e.DataObject.GetData(DataFormats.Text) as string;
if (ValidateTextInput(lPastingText) == false) { e.CancelCommand(); }
}
// Do the validation in a separate function which can be reused
private bool ValidateTextInput(string aTextInput)
{
if (aTextInput == null) { return false; }
Match lInvalidMatch = Regex.Match(aTextInput, this.mInvalidCharPattern);
return (lInvalidMatch.Success == false);
}
You've probably seen this already, but it's the simplest solution and has always worked for me. I catch the PreviewKeyDown event and..
<TextBox PreviewKeyDown="TextBox_PreviewKeyDown" Width="150" Height="30"></TextBox>
private void TextBox_PreviewKeyDown(object sender, KeyEventArgs e)
{
... validation here, eg. to stop spacebar from being pressed, you'd use:
if (e.Key == Key.Space) e.Handled = true;
}
I'm using this for a Windows Phone Runtime 8.1 app to allow only certain characters:
<TextBox x:Name="TextBoxTitle"
MaxLength="24"
InputScope="AlphanumericHalfWidth"
TextChanged="TextBoxTitle_TextChanged"
KeyUp="TextBoxTitle_KeyUp"
Paste="TextBoxTitle_Paste"/>
using System.Text.RegularExpressions;
bool textBoxTitle_TextPasted = false;
private void TextBoxTitle_Paste(object sender, TextControlPasteEventArgs e)
{
textBoxTitle_TextPasted = true;
}
// only allow characters A-Z, a-z, numbers and spaces
private void TextBoxTitle_TextChanged(object sender, TextChangedEventArgs e)
{
string fileNameCompatibleString = Regex.Replace(TextBoxTitle.Text, "[^a-zA-Z0-9\x20]", String.Empty);
if (TextBoxTitle.Text != fileNameCompatibleString)
{
if (textBoxTitle_TextPasted)
{
TextBoxTitle.Text = fileNameCompatibleString;
TextBoxTitle.SelectionStart = fileNameCompatibleString.Length;
}
else
{
int selectionStartSaved = TextBoxTitle.SelectionStart;
TextBoxTitle.Text = fileNameCompatibleString;
TextBoxTitle.SelectionStart = selectionStartSaved-1;
}
}
textBoxTitle_TextPasted = false;
}
// close SIP keyboard on enter key up
private void TextBoxTitle_KeyUp(object sender, KeyRoutedEventArgs e)
{
if (e.Key == Windows.System.VirtualKey.Enter)
{
Windows.ApplicationModel.Core.CoreApplication.GetCurrentView().CoreWindow.IsInputEnabled = false;
Windows.ApplicationModel.Core.CoreApplication.GetCurrentView().CoreWindow.IsInputEnabled = true;
e.Handled = true;
}
}
Going after the TextBox PreviewKeyUp event worked well. Captured the current text in the text box by casting the sender as a TextBox. Then used a RegEx replace to replace invalid characters. Could also add some tool tip text in here as well, but for now this removes invalid characters and turns the background red for instant user feedback.