How to access controls located in the listview from codebehind? - c#

I have a ListView called CouncilListView and a TextBox called EmailTextBox which is in the ListView.
How can I access this TextBox from the CodeBehind?
I tried some forms of FindControl like :
this.Page.FindControl("EmailTextBox");
this.Page.FindControl("CouncilListView").FindControl("EmailTextBox");
this.CouncilListView.Findcontrol("EmailTextBox");
this.FindControl("EmailTextBox");
but I get this error:
Object reference not set to an instance of an object.

This is hypothetical, since I can't see your complete page codebehind and ListView code, but:
The reason is that the Textbox is part of the Listview; so you need to find it in the ListView. One possible way of doing this is below.
public void GetTextBoxValuesFromListView()
{
Textbox tb = null;
ListViewItem Item = null;
foreach (ListViewDataItem item in CouncilListView.Items)
{
Item = item;
tb = ((TextBox) (Item.FindControl("EmailTextBox")));
if (tb.Text != null)
{
//Do something
}
}
}
I had some issues with ListViews I had questions on some time back, they may be of use to you:
ListView DataItem Shows Null
Dictionary<T> of List<T> and ListViews in ASP.NET

I solved it this way:
protected void CouncilListView_ItemInserted(Object sender, ListViewInsertedEventArgs e)
{
foreach (DictionaryEntry Emailentry in e.Values)
{
if (Emailentry.Key == "Email") //table field name is "email"
{
message.To.Add(new MailAddress(Emailentry.Value.ToString()));
}
}
}

Related

Changing SelectedItem property of a ListView programatically

I have a 2 ListViews with same items in both of them. What I want to do is that when a selection is made in one ListView, the same selection should be reflected in the other ListView also. The two ListViews are bound to two different ViewModels but both the ViewModels implement the same interface.
I've overridden the Equals methods in both ViewModels.
The two ListViews are on different XAML pages. The first ListView say LV1 is in Page1.xaml and LV2 is in Page2.xaml. What I want is that when I am changing the selection in LV2 the selection in LV1 should also change( one way only ). I've set x:FieldModifier="public" on LV1 and exposing through a static property of Page1 like this:
public sealed partial class Page1 : Page
{
public static Page1 page1 { get; private set; }
}
And on Page2, I have this :
private async void LV2_ItemClick(object sender, ItemClickEventArgs e)
{
var selected = e.ClickedItem as ISomeCommonInterface;
//Comparision is successful --> Contains() always returns corect value;
if (Page1.page1.LV1.Items.ToList().Contains(selected))
{
Page1.page1.LV1.SelectedItem = null; // this works
Page1.page1.LV1.SelectedItem = selected; // this doesn't work
}
}
I've found that inside the if condition, assignment to null changes the SelectedItem of LV1 to null but the next line doesn't change it to selected ( it remains null ).
add after assignment:
Page1.page1.LV1.Select();
This works for me:
private void LV1_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
var selected = (sender as ListView).SelectedItem as string;
int index = -1;
for (int i = 0; i < LV2.Items.Count(); i++)
{
if (LV2.Items[i] as string == selected){
index = i;
break;
}
}
// The if becomes obsolete here, it could be replaced by
// if(index >= 0)
if (LV2.Items.ToList().Contains(selected))
{
LV2.SelectedIndex = index;
}
}
There is probably an easier way of getting the index of LV1's SelectedItem in LV2, but it should be enough to get you on the right track.
You can check out the minimal testing app I created that shows that SelectedItem works too.
Method 1 - SelectionMode="Multiple" - both ListViews in sync
You should subscribe the SelectionChanged event on both ListViews - item may not get selected only by click - and there (when selection is changed) you should sync the selection.
private void SyncSelection(object sender, SelectionChangedEventArgs e)
{
ListView listViewToAdd = ReferenceEquals(sender, firstListView) ? secondListView : firstListView;
foreach (var item in e.AddedItems)
{
if (!listViewToAdd.SelectedItems.Contains(item))
{
listViewToAdd.SelectedItems.Add(item);
}
}
foreach (var item in e.RemovedItems)
{
listViewToAdd.SelectedItems.Remove(item);
}
}
Method 2 - SelectionMode="Multiple" - update one after selecting in the other
You should subscribe the SelectionChanged event only on the ListView where items could be selected.
private void SyncSelection(object sender, SelectionChangedEventArgs e)
{
foreach (var item in e.AddedItems)
{
secondListView.SelectedItems.Add(item);
}
foreach (var item in e.RemovedItems)
{
secondListView.SelectedItems.Remove(item);
}
}
Method 3 - SelectionMode="Single"
Subscribe the SelectionChanged event on both if you want to make them be in sync or only on the selectable one if you only want to update the second based on the first.
private void SyncSelection(object sender, SelectionChangedEventArgs e)
{
ListView senderListView = (ListView)sender;
ListView listViewToAdd = ReferenceEquals(sender, firstListView) ? secondListView : firstListView;
listViewToAdd.SelectedItem = senderListView.SelectedItem;
}
You may need to replace var with your interface to make it work.

How to load datagrid base in parent datagrid in wpf

I have this 2 datagrid, on selectionchanged in first datagrid it will load the data base in the id i passed in second datagrid
this is the code from first datagrid in selectionchanged event
private void equipmentDataGrid_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
try
{
var row_list = (Equipment)equipmentDataGrid.SelectedItem;
var inspectionContent = new InspectionContent();
inspectionContent.PassingValue(row_list.ID);
}
catch {
}
}
InspectionContent is the another usercontrol w/c contains the second datagrid. i passed a id value to load the data in second datagrid, my problem was the loading part is not called in the constructor, why is it the data in second datagrid is not loading?
You have to use the event args if you want to proceed in this way with the code behind
DataGrid dataGrid = sender as DataGrid;
if (sender != null && e.AddedItems.Count > 0) {
var row = e.AddedItems[0] as Equipment;
if (row != null)
{
inspectionContent.PassingValue(row.ID);
Alternatively, for the future, you may want to study the MVVM approach that is based on property binding ...
Please note also that your try/catch is very bad, since it silently discard any exception, at least track the error in debug
catch (Exception exc) {
Debug.WriteLine (exc.Message + exc.StackTrace);
}
This creates a new instance of the InspectionContent UserControl:
var inspectionContent = new InspectionContent();
You want to call the PassingValue of the already created instance that you see on the screen.
Give it a name ("uc" in the below sample) in your XAML markup:
<local:InspectionContent x:Name="uc" ...>
...and access it using this name in the event handler:
private void equipmentDataGrid_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
var row_list = (Equipment)equipmentDataGrid.SelectedItem;
uc.PassingValue(row_list.ID);
}

Clearing All ComboBoxes method

I am trying to create a method that will clear all of the ComboBoxes on my window. This is what I have tried so far:
private void ClearAllComboboxes(ComboBox cmb)
{
cmb.SelectedIndex = -1;
}
And then I call the method like below, but I can only insert one ComboBox to clear at a time.
private void btnClearAll_Click(object sender, RoutedEventArgs e)
{
ClearAllComboboxes(cmbBarlocks);
}
So what I am trying to do is clear all of the comboboxes with as little coding as possible. Can someone please tell me how and what would be the best possible way to do this? Thank you :)
I assume that you are using MVVM and you have SelectedItem property for every combobox in your viewmodel.
In viewmodel, you can just set SelectedItem=null for each combobox.
It will clear your combobox selection.
If you are not using MVVM, then you can use following code in code behind:
private void ClearAllComboboxes()
{
List<ComboBox> comboBoxes = new List<ComboBox>();
GetLogicalChildCollection<ComboBox>(container, comboBoxes);
comboBoxes.ForEach(combobox => combobox.SelectedIndex = -1);
}
private static void GetLogicalChildCollection<T>(DependencyObject parent,List<T> logicalCollection) where T : DependencyObject
{
var children = LogicalTreeHelper.GetChildren(parent);
foreach (object child in children)
{
if (child is DependencyObject)
{
DependencyObject depChild = child as DependencyObject;
if (child is T)
{
logicalCollection.Add(child as T);
}
GetLogicalChildCollection(depChild, logicalCollection);
}
}
}
Let me assume All your comboboxes are inside a container(let it be stackPanel), the you can set selected index to -1 for all of them using the following snippet:
foreach (Control ctrl in stkContainer.Children)
{
if (ctrl.GetType() == typeof(ComboBox))
{
ComboBox cbo = ctrl as ComboBox;
ClearAllComboboxes(cbo);
}
}
If you want to clear the combobox means you have to re-define your method signature as:
private void ClearAllComboboxes(ComboBox cmb)
{
cmb.Items.Clear();
}
protected void btnAll_Click(object sender, EventArgs e)
{
ClearInputs(Page.Controls);
}
//For Clear All Control Values
void ClearInputs(ControlCollection ctrls)
{
foreach (Control ctrl in ctrls)
{
if (ctrl is ComboBox )
((ComboBox )ctrl).ClearSelection();
ClearInputs(ctrl.Controls);
}
}
In your handler try this, it worked when I had a similar issue with ListBox
void ClearCombos(params ComboxBox[] boxes)
{
foreach(var box in boxes)
box.ItemsSource = null;
}
and call it ClearCombos(x,y,z); where x,y,z are the boxes you want to clear

WPF ObservableCollection: How to add a blank line in one form's combobox, but not actually affect the ObservableCollection?

I have a static ObservableCollection in a Data Repository class. I use it to populate a combobox on one of my forms (which needs to be able to include a blank line which represents NULL).
I use the same ObservableCollection to populate a DataGrid, so I don't want the blank item in the actual ObservableCollection. How do I actually do this?
Oh, and the reason I want to do this is so that if I have both forms open and I delete an item from the ObservableCollection it should reflect that in both of the lists.
You can't select null value in combobox.
You have to use blank item to display it in the control.
I have the same problem and i'm using this solution in my current project:
public class ObservableCollectionCopy<T> : ObservableCollection<T>
{
public ObservableCollectionCopy(T firstItem, ObservableCollection<T> baseItems)
{
this.FirstItem = firstItem;
this.Add(firstItem);
foreach (var item in baseItems)
this.Add(item);
baseItems.CollectionChanged += BaseCollectionChanged;
}
public T FirstItem { get; set; }
private void BaseCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
if (e.NewItems != null)
foreach (var newItem in e.NewItems.Cast<T>().Reverse())
this.Insert(e.NewStartingIndex + 1, newItem);
if (e.OldItems != null)
foreach (var oldItem in e.OldItems.Cast<T>())
this.Remove(oldItem);
}
}
New collection has one-way binding to base collection:
this.SelectableGroups = new ObservableCollectionCopy<GroupModel>(
new GroupModel{Id = -1, Title = "Any group"},
this.GroupsCollection);
Filtering:
if (this.selectedGroup != null && this.selectedGroup.Id != -1)
this.MyCollectionView.Filter = v => v.SomeItem.GroupId == this.selectedGroup.Id;
else this.MyCollectionView.Filter = null;
You might be able to use the TargetNullValue property of a binding declaration to declare output for a null value.
<ComboBox ItemsSource={Binding Path=Collection, TargetNullValue="-------"}/>

Get the selected value of a dropdownlist located in a listview

how can i get the selected value from a dropdownlist which is in a listview , from the DropDownList_SelectedIndexChanged event?
i have always had problem with finding controls in the page :-)
foreach (ListViewItem item in CouncilListView.Items)
{
CouncilIdLabel = (Label)item.FindControl("CouncilIdLabel");
}
it just pass all the items and i don't know how to get out of the foreach when reach the wanted control.
If you are registering the event from within the template markup of your listview like so:
<asp:DropDownList runat='server' id='ddl1' OnSelectedIndexChange='dropdownlist_selectedindexchange' />
then all you have to do is this:
protected void dropdownlist_selectedindexchange(Object sender, EventArgs e){
DropDownList ddl1 = (sender as DropDownList);
String value = ddl1.SelectedValue;
}
You can Exit the foreach loop:
string look_for = "bbb";
ArrayList names = new ArrayList();
names.Add("aaa");
names.Add("bbb");
names.Add("ccc");
foreach (string name in names)
{
if (look_for == name)
{
break;
}
}

Categories