So I have RadGridView with ContextMenu that has ItemClick event with this code :
ListData selectedItem = new ListData();
public void GridContextMenu_ItemClick(object sender, Telerik.Windows.RadRoutedEventArgs e)
{
MenuItem item = (e.OriginalSource as RadMenuItem).DataContext as MenuItem;
switch (item.Text)
{
case "Edit":
selectedItem = (GridView.SelectedItem);
editMenu.Show();
this.Close();
break;
case "Delete":
this.GridView.Items.Remove(this.GridView.SelectedItem);
break;
}
}
The ListData is something like this :
public class ListData
{
public string Name { get; set; }
public string Type { get; set; }
...
public string Something { get; set; }
}
I know that selectedItem inside case"Edit" has one row data from Name, Type, ... , Something from the clicked row when i click the "Edit" Menu. But how can i use the selectedItem in other method in the same .xaml.cs or even in other file?
OK, I'm not sure if this is exactly what you need, but here is what worked for me.
At the top of the class I have this :public ListData selectedItem;
Inside the class constructor I have this: selectedItem = new ListData();
and also this public ObservableCollection<ListData> OCLData;
I created a datagrid named dgMirza, and set the ItemsSource = OCLData. OCLData is a collection of ListData objects.
Inside the SelectedCellsChanged event I put this: selectedItem = (ListData)dgMirza.SelectedItem;
I was able to see data in the selectedItem object even in other methods.
Related
I have an ObservableCollection<string> named MyCollection containing "A", "B", "C", "D". I create a view like this:
<ComboBox x:Name="MyComboBox"
ItemsSource="{Binding MyCollection}"
SelectedIndex="{Binding 3}"/>
<Button Click="OnClickButton">Button</Button>
Then my codebehind looks like this:
public partial class MyClass {
private string _mySelection;
public string MySelection
{
get { return _mySelection; }
set
{
_mySelection = value;
}
}
public void OnClickButton(object sender, RoutedEventArgs e) {
MySelection = (MyComboBox.SelectedItem).ToString();
MessageBox.Show(MySelection);
}
This is fine. The ComboBox populates just as it should, and MySelection is set properly and appears in the message box. But currently, my ComboBox appears blank in the user interface until the user clicks on it and selects an option. I want option C to be the default value, and if the user doesn't select anything, then MySelection will be set to C.
But no matter how many different combinations of SelectedItem, SelectedValue, and SelectedIndex I try, I can't get it to work. The ComboBox always starts off empty.
How can I do this?
Set a default value of the _mySelection field, i.e. "C"
Or, more general, set the value of MySelection to the desired default value after construction.
Also make sure that the MySelection property fires a change notification.
public class MyViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public ObservableCollection<string> MyCollection { get; }
= new ObservableCollection<string>();
private string mySelection;
public string MySelection
{
get { return mySelection; }
set
{
mySelection = value;
PropertyChanged?.Invoke(this,
new PropertyChangedEventArgs(nameof(MySelection)));
}
}
}
Initialize the DataContext of the view with an instance of MyViewModel:
public MainWindow()
{
InitializeComponent();
var vm = new MyViewModel();
vm.MyCollection.Add("A");
vm.MyCollection.Add("B");
vm.MyCollection.Add("C");
vm.MyCollection.Add("D");
vm.MySelection = "C";
DataContext = vm;
}
private void OnClickButton(object sender, RoutedEventArgs e)
{
MessageBox.Show(((MyViewModel)DataContext).MySelection);
}
I create a simple Treeview that I bound to an ObservableCollection.
ObservableCollection<IMarketDataViewModel> MarketDataItems;
public interface IMarketDataViewModel
{
string Title { get; }
ObservableCollection<IMarketDataViewModel> Items { get; set; }
}
public MarketDataUserControl(IMarketDataViewer viewModel)
{
InitializeComponent();
DataContext = viewModel;
marketDataTreeView.ItemsSource = viewModel.MarketDataItems;
}
When I update data in my ViewModel, I only see the first level in my Treeview. The only way I found to resolve the problem is to create an event in my ViewModel and when the data is updated instead calling PropertyChange on MarketDataItems, I trigger the event and the View reset marketDataTreeView.ItemsSource like this :
private void ViewModelOnOnUpdateItems()
{
marketDataTreeView.ItemsSource = null;
marketDataTreeView.ItemsSource = viewModel.MarketDataItems;
}
And this work perfectly --> All levels are displayed.
Someone know why the PropertyChange doesn't work and why I have to reset the ItemsSource ?
I think you should implement a binding to the ItemSource and this is done by a property:
// Create property
public ObservableCollection<IMarketDataViewModel> MarketDataItems { get; private set; }
...
// Create Binding
Binding bindingObject = new Binding("MarketDataItems");
bindingObject.Source = this; //codebehind class instance which has MarketDataItems
marketDataTreeView.SetBinding(TreeView.ItemsSource, bindingObject);
Or the binding in XAML:
<TreeView x:Name="marketDataTreeView" ItemsSource="{Binding Path=MarketDataItems}"/>
Finally the issue is that I didn't call OnPropertyChanged("Items")
public class MarketDataViewModelBase : IMarketDataViewModel, INotifyPropertyChanged
{
.....
private ObservableCollection<IMarketDataViewModel> items;
public ObservableCollection<IMarketDataViewModel> Items
{
get { return items; }
set
{
items = value;
OnPropertyChanged("Items"); //Add this line fix my issue
}
}
}
Hi I have a list box with some customer names, I want to filter the list based on the text entered in the TextBox. After researching a bit I heard that we can use CollectionViewSourse and ICollectionView but did not get a stage where I could get it working.
Could you please suggest on how to achieve this.
Your help is much appreciated.
XAML
<TextBox x:Name="txtSearch"/>
<ListBox x:Name="lbCustomers">
XAML.cs
List<string> customerList;
public MainPage()
{
this.InitializeComponent();
customerList = new List<string>();
customerList.Add("Andrew");
customerList.Add("bravo");
customerList.Add("Carol");
customerList.Add("Dela");
customerList.Add("Eva");
customerList.Add("family");
customerList.Add("George");
customerList.Add("Health");
customerList.Add("Illa");
customerList.Add("Jack");
customerList.Add("Andrew");
lbCustomers.ItemsSource = customerList;
CollectionViewSource collectionViewSource = new CollectionViewSource();
collectionViewSource.Source = customerList;
ICollectionView collectionView = collectionViewSource.View;
}
Edit:
I can not access 'CollectionViewSource.GetDefaultView' and 'view.Filter'. I get an error : 'collectionviewsource does not contain a definition for getdefaultview'
When I looked into the definition i did not find the 'GetDefaultView' and 'Filter dependency properties'
public sealed class CollectionViewSource : DependencyObject, ICollectionViewSource
{
public CollectionViewSource();
public static DependencyProperty IsSourceGroupedProperty { get; }
public static DependencyProperty ItemsPathProperty { get; }
public static DependencyProperty SourceProperty { get; }
public static DependencyProperty ViewProperty { get; }
public System.Boolean IsSourceGrouped { get; set; }
public PropertyPath ItemsPath { get; set; }
public System.Object Source { get; set; }
public ICollectionView View { get; }
}
Try getting the default collection view for your collection. Every time your txtSearch changes you have to change the filter.
ICollectionView view = CollectionViewSource.GetDefaultView(customerList);
view.Filter = obj =>
{
string item = obj as string;
return (item.ToLower().Contains(YourFilter));
};
I would advice you to read about data binding and how it use it to bind listboxes and textboxes and manage your collections in your viewmodels.
But to fix your problem as it is.
Define your IcollectionView at a global level just like customerList and in your main change your code to
CollectionViewSource collectionViewSource = new CollectionViewSource();
collectionViewSource.Source = customerList;
collectionView = collectionViewSource.View;
collectionView.Filter = collectionFilter;
lbCustomers.ItemsSource = collectionView;
and add these 2 additional methods
private bool collectionFilter(object obj)
{
if (string.IsNullOrWhiteSpace(txtSearch.Text))
return true;
string name = obj.ToString();
return name.Contains(txtSearch.Text);
}
private void TxtSearch_OnTextChanged(object sender, TextChangedEventArgs e)
{
collectionView.Refresh();
}
change textbox to
<TextBox x:Name="txtSearch" TextChanged="TxtSearch_OnTextChanged"/>
These should be self explanatory changes but if you need any help i am happy to explain
The filter method is where you define your logic of filtering the listbox items on display
I'm developing a small windows store application in C# where I have populated the values and content for a listbox using the following code snippet.
code 1 : adds the song title as a item to a listbox, using the Song class to create the item
private void addTitles(string title, int value)
{
Song songItem = new Song();
songItem.Text = title;
songItem.Value = value;
listbox1.Items.Add(songItem); // adds the 'songItem' as an Item to listbox
}
code 2 : Song class which is used to set values to each item ('songItem')
public class Song
{
public string Text { get; set; }
public int Value { get; set; }
public override string ToString()
{
return Text;
}
}
Population content to the listbox is functioning currently.
What I want is to get the 'Value' of each item on a Click event, on run-time.
For that purpose, how can I read(extract) the Value of the selected Item in the listbox, in C#? ( Value is the songItem.Value )
code 3 : I have tried this code, as trying to figure out a solution, but it didn't work
private void listbox1_tapped(object sender, TappedRoutedEventArgs e)
{
Int selectedItemValue = listbox1.SelectedItem.Value();
}
Therefore it would be really grateful if someone can help me, as I'm an Amateur.
not sure about the "TappedRoutedEventArgs", but I would do
private void listbox1_tapped(object sender, TappedRoutedEventArgs e)
{
var selectedSong = (Song)listbox1.SelectedItem;
if (selectedSong != null) {
var val = selectedSong.Value;
}
}
because SelectedItem is an Object (which doesn't know about the Value property), so you have to cast it to a Song first.
By the way, Value is a property, not a method, so you don't need the parenthesis.
Try like this:
Song song=listbox1.SelectedItem as Song;
or this:
var selected = listbox1.SelectedValue as Song;
Try something like this :
if (listbox1.SelectedRows.Count>0){
Song song=(Song)listbox1.SelectedItem;
int value=song.Value;
}
DataContextDataContext context1 = new DataContextDataContext();
public MainWindow()
{
InitializeComponent();
DataContext = new ObservableCollection<MyObject>();
RadGridView1.Filtered+=new EventHandler<GridViewFilteredEventArgs>(RadGridView1_Filtered);
ObservableCollection<MyObject> _MyObject = new ObservableCollection<MyObject>();
foreach (var p in context1.Students)
{
_MyObject.Add(new MyObject { ID = p.StudentID, Name = p.StudentFN });
}
}
void RadGridView1_Filtered(object sender, GridViewFilteredEventArgs e)
{
RadGridView1.ItemsSource = ObservableCollection<MyObject>();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
}
}
public class MyObject
{
public int ID { get; set; }
public string Name { get; set; }
}
How do you bind my ObservableCollections to the ItemsSource?
You want to set the ItemSource to the instance of an ObservableCollection you created in the constructor:
RadGridView1.ItemsSource = _MyObject;
You can make the observable collection as a public property in your code-behind/presenter/viewmodel, like
public ObservableCollection<MyObject> MyObjectCollection {get;set;}
then you can populate that and the binding can be code code behind.
ItemsSource is a dependency property you can bind it in XAML or code behind, like suppose you want to bind to ListBox's(say named lstItems) ItemsSource, like (below code is considering that 'MyObjectCollection' is in codebehind
Binding bindingObject = new Binding("MyObjectCollection");
bindingObject.Source = this; //codebehind class instance which has MyObjectCollection
lstItems.SetBinding(ListBox.ItemsSource, bindingObject);
or in XAML,
<ListBox x:Name="lstItems" ItemsSource="{Binding Path=MyObjectCollection}"/>
for both the ways above you need to set the datacontext which is 'this' (for this specific solution).
But maybe you want to look into basic WPF databinding where you can understand Depedency properties, binding objects, binding modes, etc.
http://msdn.microsoft.com/en-us/library/aa480224.aspx
http://msdn.microsoft.com/en-us/library/ms750612.aspx
http://joshsmithonwpf.wordpress.com/2008/05/19/gradual-introduction-to-wpf-data-binding/