filtering is not working for Telerik RadGridView Silverlight - silverlight-4.0

I am using telerik radgridview whose item collection is domainsource bound to datapager
I have 20 pages, when i filter on the column it just filters on the current page , how do i make it to filter on the whole collection. below is my code
<telerikRad:RadGridView>
ItemsSource="{Binding ElementName=stddata, Path=Data}"
<telerikRad:RadGridView.Columns>
<telerik:GridViewDataColumn Header="stuName" DataMemberBinding="{Binding Name}" />
<telerik:GridViewDataColumn Header="StuId" DataMemberBinding="{Binding StudentId}" />
<telerikRad:RadGridView.Columns>
<telerikRad:RadGridView>
<sdk:DataPager Grid.Row="2"
x:Name="SSSS"
Source="{Binding Data, ElementName=stddata}"
IsTotalItemCountFixed="True" />
<riaControls:DomainDataSource Name="stddata"
AutoLoad="True"
PageSize="9"
QueryName="GetStudentsQuery"
DomainContext="{Binding DomainContext}">
</riaControls:DomainDataSource>

Telerik provides for getting the filtered items indirectly by applying the filter from the RadGridView to the collection that the control is bound to.
Here is a solution that allows one to get a filtered, sorted list of data items using the current filter and sort settings from a Telerik RadGridView control.
using Telerik.Windows.Data;
.
.
.
IEnumerable<MyClass> itemsToDisplay { get; set; } //The RadGridView is bound to this property
public void DoSomethingWithFilteredAndSortedDisplayItems(RadGridView rgv)
{
IQueryable<MyClass> iqItems = itemsToDisplay.AsQueryable();
FilterDescriptorCollection filter = rgv.FilterDescriptors;
SortDescriptorCollection sort = rgv.SortDescriptors;
List<MyClass> fsItems = iqItems.Where(filter).Sort(sort).ToIList() as List<MyClass>;
if (fsItems != null && fsItems.Count > 0)
{
DoSomethingWithDisplayItems(fsItems);
}
}
public void DoSomethingWithDisplayItems(IEnumerable<MyClass> list)
{
... //Do something
}
This is for illustration. In my own code I implement the filter and sort as an extension method for the RadGridView control.

Related

How to use Xamarin to call an UI Element with a bound name

I'm trying to use a custom variable to name UI Elements in XAML in order to use them in my Xamarin code. How would I do that?
I know that I can use the tags
<Label x:Name="CallVariable" Text="This will appear"/>
and I can call the label from Xamarin using
Label foo = FindByName("CallVariable") as Label;
and mess with the text with the following
foo.Text == "This will appear"
which should return true.
I learned about binding, and so I tried to use this in my variables.
<Label x:Name={Binding Name}/>
Label bar = FindByName(emp.training[i] as Label);
Unfortunately, every time I run it, I'm receiving the error:
System.NullReferenceException: Object reference not set to an instance of an object.
I remembered to set the BindingContext. And in case it's important, this is all happening within a list view.
Is x:Name a bindable object? Or is there another method I should be using? Maybe a way to call an object based on its label, or something?
My current task is as follows:
I have a list of people's information. Name, Age, Gender, Email, Location, and a few other pieces of information. I'm trying to get someone to search for certain types of people, have it return a list of everyone in a ListView, and have the person be able to select as many as they want. I did this using a button that adds the person to a list (or removes them from the list if they're already on). If the user chooses to, they should be able to also click "Select All" to add everyone. I've got the individual adding down, I just need to somehow select all of them.
You can't access the label with a listView by x:Name in code behind. Instead of access the label in the listView, you can bind the property of label in code behind. For example:
<ListView x:Name="testListView">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout>
<Label Text="{Binding Name}" />
<Label Text="{Binding Desc}" />
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
And in code behind, it should be:
public partial class MainPage : ContentPage
{
ObservableCollection<testViewModel> myModels = new ObservableCollection<testViewModel>();
testViewModel model;
public MainPage()
{
InitializeComponent();
testListView.ItemsSource = myModels;
myModels.Add(new testViewModel { Name = "age" });
myModels.Add(new testViewModel { Name = "gender" });
myModels.Add(new testViewModel { Name = "name" });
}
}
class testViewModel
{
public string Name { get; set; }
public string Desc { get; set; }
}
Next time you want to update the text of label:
public void test() {
//Get the model you want to change
model.Desc = "This will appear";
}
I've got the individual adding down, I just need to somehow select
all of them.
I don't know how you implement the individual adding down, share the code and maybe I can give you some suggestions.

How to mix dynamic and static items in UWP XAML NavigationView MenuItems?

I'm trying to make a NavigationViewMenu and I need a menu layed out as follows
static Home item
static Header
dynamic elements from DB as items
static Header
static set of items
This is what I tried:
<NavigationView.MenuItems>
<NavigationViewItem Icon="Home" Content="Home" Tag="home" />
<NavigationViewItemSeparator />
<NavigationViewItemHeader Content="My Stuff"/>
<NavigationViewList ItemsSource="{x:Bind MyStuff}">
<NavigationViewList.ItemTemplate>
<DataTemplate x:DataType="local:MyModel">
<NavigationViewItem Icon="Pictures" Content="{x:Bind Name}" Tag="{x:Bind Tag}" />
</DataTemplate>
</NavigationViewList.ItemTemplate>
</NavigationViewList>
<!-- Static equivalent to the above:
<NavigationViewItem Icon="Pictures" Content="Woop" Tag="foos"/>
<NavigationViewItem Icon="Pictures" Content="Doop" Tag="foos"/>
<NavigationViewItem Icon="Pictures" Content="Loop" Tag="foos"/>
-->
<NavigationViewItemHeader Content="Other Stuff"/>
<NavigationViewItem Icon="Pictures" Content="Foos" Tag="foos"/>
<NavigationViewItem Icon="ContactInfo" Content="Bars" Tag="bars"/>
<NavigationViewItem Icon="SwitchApps" Content="Bazes" Tag="bazes"/>
</NavigationView.MenuItems>
This is what I've got:
This is what I wanted:
Is there anything as good and practical as Angular's *ngFor in XAML for UWP?
I ran into the same behavior, and managed to find a work around. In my case, I had two lists of menu items (dynamically data-bound items), and I wanted to use NavigationViewItemHeader on top of both (static items). I tried using a NavigationViewList and ran into your problem.
TL;DR:
Create a list of menu items in C# code. The elements of this list can be a mix of your viewmodels, and any static Navigation Items (headers, separators, etc). Then use a DataTemplateSelector to either databind to your viewmodel or pass-through the navigation items unchanged.
More detailed
In your C# code-behind, create an enumerable (or observable collection) of your menu items. In my case SomeCollection and AnotherCollection represent my data sources that I wanted to bind to my NavigationView. I have to type it as object because it's a mix of my viewmodels and the built-in UWP navigation item types.
private IEnumerable<object> MenuItems()
{
yield return new NavigationViewItemHeader { Content = "Some List" };
foreach (var some in SomeCollection)
{
yield return some;
}
yield return new NavigationViewItemHeader { Content = "Another List" };
foreach (var another in AnotherCollection)
{
yield return another;
}
}
// somewhere else, like in your Page constructor or a CollectionChanged handler
this.NavigationList = MenuItems().ToList();
Second, create a Data Template Selector to switch between your template and the navigation items:
class NavigationItemTemplateSelector : DataTemplateSelector
{
public DataTemplate ViewModelTemplate{ get; set; }
public DataTemplate NavigationItemTemplate { get; set; }
protected override DataTemplate SelectTemplateCore(object item)
{
return item is MyViewModel
? ViewModelTemplate
: NavigationItemTemplate;
}
}
Finally, change your NavigationView to reference the template selector and menu item source. The NavigationItemTemplate is just a pass-through, and your ViewModelTemplate would have the normal viewmodel item binding logic.
<Page.Resources>
<DataTemplate x:Key="ViewModelTemplate" x:DataType="local:MyViewModel">
<TextBlock Text="{x:Bind SomeProperty}" />
</DataTemplate>
<DataTemplate x:Key="NavigationItemTemplate">
</DataTemplate>
<local:NavigationItemTemplateSelector x:Key="NavigationItemTemplateSelector"
ViewModelTemplate="{StaticResource ViewModelTemplate}"
NavigationItemTemplate="{StaticResource NavigationItemTemplate}" />
</Page.Resources>
<NavigationView
MenuItemsSource="{x:Bind NavigationList, Mode=OneWay}"
MenuItemTemplateSelector="{StaticResource NavigationItemTemplateSelector}">
<Frame x:Name="ContentFrame"></Frame>
</NavigationView>
I can reproduce it. It looks like NavigationViewList only take the space of one item when putting itself in NavigationView.MenuItem. Which is the same like putting a ListView in a ListViewItem. To change this behavior we need to change the item's behaviour ourselves. However after some investigating it seems currently customization of NavigationViewList is blackbox for us. So the only way I could think is to build our own NavigationView with the help of splitview and acrylic.
I didn't find it necessary to use different templates as in the accepted answer, maybe because there were some changes in the underlying Windows code in the meantime. As I needed a stable part of the menu and then a dynamic part depending on the actual page, I created an interface:
interface IMenuProvider {
IEnumerable<NavigationViewItemBase> GetMenuItems();
}
and made sure all my pages implement it. My MainPage returns the fixed part:
public IEnumerable<NavigationViewItemBase> GetMenuItems() {
yield return new NavigationViewItem {
Tag = "home",
Icon = new SymbolIcon(Symbol.Home),
Content = "Home",
};
yield return new NavigationViewItemSeparator();
yield return new NavigationViewItem {
Tag = "xxx",
Icon = new SymbolIcon(Symbol.XXX),
Content = "XXX",
};
}
the other pages, similary, provide their own menu headers and items.
When I navigate the pages, I change the menu as well, concatenating the fixed and variable parts:
ContentFrame.Navigate(PageType, null, transitionInfo);
if (ContentFrame.Content is IMenuProvider menuProvider)
= GetMenuItems().Concat(menuProvider.GetMenuItems()).ToList();
(Or, you might place the menu change into the Navigated handler of the Frame.)
While it's still a nuisance that these menus, at least the fixed part, cannot be declared in XAML, this approach works.

Dynamically change DataTemplate for a ListView at Runtime

I have 2 DataTemplates for displaying the contents of ClassA or ClassB inside a single ListView; which template to select will be based on a RadioButton selection by the user.
Is it possible to change the ItemTemplate of a ListView (in XAML) based on user input dynamically at runtime?
An example snippet of code:
XAML Page:
<Page...>
<Page.Resources>
<DataTemplate x:Key="ClassAListViewItemTemplate" x:DataType="vm:ClassA" ... />
<DataTemplate x:Key="ClassBListViewItemTemplate" x:DataType="vm:ClassB" ... />
</Page.Resources>
<RelativePanel>
<RadioButton Content="ClassA" ... />
<RadioButton Content="ClassB" ... />
<ListView DataContext="{Binding Path=MainViewModel}"
ItemsSource="{Binding ListOfClassAOrB, Mode=TwoWay}"
ItemTemplate="{StaticResource ClassAListViewItemTemplate}"/>
</RelativePanel>
</Page>
I have stripped the code down somewhat to the essentials, but I would like to be able to change the following at runtime:
ItemTemplate="{StaticResource ClassAListViewItemTemplate}"
I have seen solutions for Classic WPF applications that use Style.Triggers, but these aren't applicable for UWP
Marco Minerva's blog on Adaptive Triggers, RelativePanel and DataTemplate in the Universal Windows Platform talks of using UserControls within DataTemplates to modify the visual state using Adaptive Triggers, but this doesn't take into account switching out of templates based on user input
The closest answer I have found to my problem is another blog he wrote "Dynamically choose DataTemplate in WinRT" where there is an element of code-behind involved - but it only appears to be an if statement - but its the cleanest solution I have come across thus far, and what I'd like to replicate in XAML
Thanks
you need to use overwrite SelectTemplateCore of Data template. Change your view model like this.
Below code will helps you.
public class SampleViewModel : DataTemplateSelector
{
public DataTemplate ClassAListViewItemTemplate{ get; set; }
public DataTemplate ClassBListViewItemTemplate{ get; set; }
protected override DataTemplate SelectTemplateCore(object item, DependencyObject container)
{
var itemsData = item as SampleClass; // add your Data class
if (itemsData.IsAddButton == false) // define any property to select the datatemplate
{
return ClassAListViewItemTemplate;
}
else
{
return ClassBListViewItemTemplate;
}
}
}
Add your two datatemplates to one key, and give the key to ItemTemplateSelector property in gridview.
<viewModels:SampleViewModel x:Key="FeedbackTempateSelector"
ClassAListViewItemTemplate="{StaticResource ClassAListViewItemTemplate}"
ClassBListViewItemTemplate="{StaticResource ClassBListViewItemTemplate}">
</viewModels:SampleViewModel>

PivotItem header changes during runtime

I ran into a weird problem working with the Windows Phone 8 pivot control.
Apparently, when the Pivot is bound to a list of models and the HeaderTemplate is used for binding to one of the model's properties, changing the property during runtime causes layout problem in the headers.
Here is the sample code.
Create a simple model class.
public class MyModel: INotifyPropertyChanged
{
private string _displayName;
public event PropertyChangedEventHandler PropertyChanged;
public string DisplayName
{
get
{
return _displayName;
}
set
{
_displayName = value;
if(PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs("DisplayName"));
}
}
}
}
Then initialize the model list (could occur in the ViewModel, or page's code)
Items = new List<MyModel>
{
new MyModel { DisplayName = "model 1" },
new MyModel { DisplayName = "model 2" },
}
Connecting the list of models to the pivot control
<phone:Pivot ItemsSource="{Binding Items}" DisplayMemberPath="DisplayName">
<phone:Pivot.HeaderTemplate>
<DataTemplate>
<TextBlock Text="{Binding DisplayName}" />
</DataTemplate>
</phone:Pivot.HeaderTemplate>
</phone:Pivot>
So now we have 2 pivot items and the headers are displayed correctly. Now we change DisplayName property of the first item during app runtime (say following a button click) and assign a longer string value:
Items[0].DisplayName = "Some other header";
This causes the headers to overlap.
Any thoughts?
Elad
if you set displayName property to "Some other header" at first time, and then change the value to "model 2", normal display. So, in my opinion, this problem was caused by the pivot header width property(in your code,the textblock's width). When the pivot was loaded, every header had fixed width, and at this time, you changed the header display name to a longger value, the pivot will not be display correctly.

XAML/C#: What event fires after reordering a gridview?

I am making my first Windows Store app in Visual Studios 2012. I have a gridview control that I have enabled to be reordered. I have code that I need to run when the list is reordered. I have tried the Drop event. It does not fire. I tried several other drag events, which also did not fire. It seems like this should be so simple... Thanks for your time!
You cannot reorder a GridView unless the ItemsSource is bound to an ObservableCollection and CanReorderItems, CanDragItems, and AllowDrop are set to true. It is not necessary to use a CollectionViewSource to enable reordering in your gridview. In fact, a collectionviewsource is often used for grouping a gridview and reordering is not possible when data is grouped.
Anyway, your XAML would look like this:
<Grid Background="Black">
<Grid.DataContext>
<local:MyModel/>
</Grid.DataContext>
<GridView CanReorderItems="True" CanDragItems="True" AllowDrop="True"
ItemsSource="{Binding Items}">
</GridView>
</Grid>
Although any enumerable can be bound to the ItemsSource of a GridView it is only an ObservableCollection that enables reorder. Yes, you can use a custom type that implements reorder, but why mess with that when ObservableCollection does it for you?
Your view model might look like this:
public class MyModel
{
public MyModel()
{
foreach (var item in Enumerable.Range(1, 50))
Items.Add(item);
Items.CollectionChanged += Items_CollectionChanged;
}
ObservableCollection<int> m_Items = new ObservableCollection<int>();
public ObservableCollection<int> Items { get { return m_Items; } }
object m_ReorderItem;
int m_ReorderIndexFrom;
void Items_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
switch (e.Action)
{
case NotifyCollectionChangedAction.Remove:
m_ReorderItem = e.OldItems[0];
m_ReorderIndexFrom = e.OldStartingIndex;
break;
case NotifyCollectionChangedAction.Add:
if (m_ReorderItem == null)
return;
var _ReorderIndexTo = e.NewStartingIndex;
HandleReorder(m_ReorderItem, m_ReorderIndexFrom, _ReorderIndexTo);
m_ReorderItem = null;
break;
}
}
void HandleReorder(object item, int indexFrom, int indexTo)
{
Debug.WriteLine("Reorder: {0}, From: {1}, To: {2}", item, indexFrom, indexTo);
}
}
In the code above, the reorder event is not real. It is derived from a combination of the "Remove" action and the "Add" action in the CollectionChanged event. Here's why this is awesome. If the reorder was only available from the GridView then the ViewModel would not be able to handle it. Because the underlying list is how you detect reorder, the ViewModel is enabled.
Every case is slightly different. You may not care about the Index so you can simplify the code. You may not allow adding or removing from the collection so you only need to monitor the Add action. Again, it depends on your situation. My sample code above should get 99% of the cases taken care of.
Remember, GridView is not the only control that allows reorder. Any control based on ListViewBase (like the ListView) supports reorder - still using ObservableCollection. But GridView is the most common control to use this feature. For sure.
Reference: http://msdn.microsoft.com/en-us/library/windows/apps/windows.ui.xaml.controls.listviewbase.canreorderitems
Oh, to answer your question!
There is no event that indicates a reorder. Reorder is a derived action based on a combination of actions in the underlying ObservableCollection CollectionChanged event. Make sense?
By the way, here's sample syntax to bind to a CollectionViewSource, if you choose to:
<Grid Background="Black">
<Grid.DataContext>
<local:MyModel/>
</Grid.DataContext>
<Grid.Resources>
<CollectionViewSource x:Name="CVS" Source="{Binding Items}" />
</Grid.Resources>
<GridView CanReorderItems="True" CanDragItems="True" AllowDrop="True"
ItemsSource="{Binding Source={StaticResource CVS}}" >
</GridView>
</Grid>
Best of luck.