WPF - get all children from code - c#

Here is my problem : I created a programm with Fluent ribbon, and when I want to disable a ribbon, I need to use the following code :
Code WPF :
<Fluent:RibbonGroupBox x:Name="GpRibbonFormats" ...>
<Fluent:Button x:Name="AjoutTole" Header="{x:Static p:Resources.Ajouter}">
<Fluent:Button.ToolTip>
<Fluent:ScreenTip x:Name="ScreenTipAjoutTole"...>
</Fluent:ScreenTip>
</Fluent:Button.ToolTip>
</Fluent:Button>
<Fluent:Button x:Name="EditQtyFormat" ...>
<Fluent:Button.ToolTip>
<Fluent:ScreenTip x:Name="ScreenTipEditQtyFormat"...>
</Fluent:ScreenTip>
</Fluent:Button.ToolTip>
</Fluent:Button>
<Fluent:Button x:Name="DeleteFormat" SizeDefinition="Large">
<Fluent:Button.ToolTip>
<Fluent:ScreenTip x:Name="ScreenTipDeleteFormat" ...>
</Fluent:ScreenTip>
</Fluent:Button.ToolTip>
</Fluent:Button>
</Fluent:RibbonGroupBox>
Code Behind :
AjoutTole.IsEnabled = false;
ScreenTipAjoutTole.DisableReason = isBlocked;
EditQtyFormat.IsEnabled = false;
ScreenTipEditQtyFormat.DisableReason = isBlocked;
DeleteFormat.IsEnabled = false;
ScreenTipDeleteFormat.DisableReason = isBlocked;
It works fine but I would like to make a function like that, so I am sure I always send correct information in DisableReason :
DisableButton(Fluent:Button NameOfButton,string ReasonOfDisable)
{
NameOfButton.IsEnabled = false;
NameOfButton.AllScreenTipChild.DisableReason=ReasonOfDisable
}
The same way I would like to disable all a group of buttons :
DisableGroup(Fluent:RibbonGroupBox myGroup,string ReasonOfDisable)
{
foreach(Fluent:Button button in myGroup)
{
button.isEnable=false;
button.AllScreenTipChild.DisableReason=ReasonOfDisable;
}
}
How such a thing is it possible?I want to be able to do it from codebehind.
Edit :
When trying to get the children of my button, I return one element of type System.Windows.Controls.Border, which name is "border", but I don't have such element in my XAML file.
I also tried to get children of my RibbonGroupBox, but in that case I return one grid (grid2), and that grid is not even in the Ribbon...
Code used :
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(DeleteOL); i++)
{
var child = VisualTreeHelper.GetChild(DeleteOL, i);
string monType = child.GetType().ToString();
if(monType== "System.Windows.Controls.Border")
{
System.Windows.Controls.Border bb = (System.Windows.Controls.Border)child;
string name = bb.Name;
}
}
Edit 2 :
I confirm that getChild doesn't work on ribbon(why?), but I could find how to get list of buttons in a group :
foreach(var item in GpRibbonFormats.Items)
{
if(item.GetType().ToString()=="Fluent.Button")
{
Fluent.Button button = (Fluent.Button)item;
button.IsEnabled = false;
}
}
Now I am still looking on how to find a button's ScreenTip

You seem to mix namespace convention from XAML and C#, in C# you don't use : to reference a namespace, you use . separator instead. For example, StackPanel is inside System.Windows.Controls namespace, so you refer to it like this in C# :
System.Windows.Controls.StackPanel stackPanel = new System.Windows.Controls.StackPanel();
I never tried Fluent, but this code should work.
public void DisableGroup(Fluent.RibbonGroupBox ribbonGroup, string reasonOfDisable)
{
foreach (var item in ribbonGroup.Items)
{
if (item is Fluent.Button)
{
DisableButton((Fluent.Button)item, reasonOfDisable);
}
}
}
public void DisableButton(Fluent.Button button, string reasonOfDisable)
{
button.IsEnabled = false;
if (button.ToolTip is Fluent.ScreenTip)
{
Fluent.ScreenTip screenTip = (Fluent.ScreenTip)button.ToolTip;
screenTip.DisableReason = reasonOfDisable;
}
}
To disable an entire group, you call it like this
DisableGroup(GpRibbonFormats, "Ce groupe n'est pas disponible");
To disable only one button, you call it like this
DisableButton(AjoutTole, "Ajouter est désactivé pour le moment");
By the way, Fluent.RibbonGroupBox inherits from ItemsControl, this control has its own IsEnabled property, you can probably disable an entire group by just setting the property to false (I've not tested it though), but you'll have to go through each button to set their screentip anyway.
GpRibbonFormats.IsEnabled = false;
For this kind of thing, Binding are very powerful in WPF, you might want to read a bit on MVVM. It's not easy to implement at first, but once you get the hang of it, it's a game changer and really simplifies your code and logic.

It took time to me, but I finally understood what users were trying to explain to me (it is not obvious for somebody starting with MVVM, that's why I write it here).
I believed I could easily set my properties IsEnabled to true or false in the code(As in Roger Leblanc answer), then continue binding my ViewModel.
It is not so, as when I set my IsEnable (to true) Property, it replaces IsEnabled="{Binding EnableEditNesting}" by IsEnabled=true, so after that no more binding is done(tell me if I am wrong).
On the end I did the following :
For the GroupBox that don't need different behaviour for each button, I just put a binding on its IsEnable parameter.
<Fluent:RibbonGroupBox x:Name="GpRibbonFormats" IsEnabled="{Binding EnableGpRibbonFormats}" Header="{x:Static p:Resources.Stock}">
<Fluent:RibbonGroupBox.ToolTip>
<Fluent:ScreenTip x:Name="ScreenTipGpRibbonFormats" Image="img\image_engrenage.png" Width="250" Text="{x:Static p:Resources.NestingSendToProduction}" DisableReason="{Binding EnableGpRibbonFormatsReason}">
</Fluent:ScreenTip>
</Fluent:RibbonGroupBox.ToolTip>
<Fluent:Button x:Name="AjoutTole" SizeDefinition="Large" LargeIcon="img\image_add.png" Header="{x:Static p:Resources.Ajouter}" Click="Add_ToleOL_Click">
</Fluent:Button>
...
</Fluent:RibbonGroupBox>
For the GrouBox where I need specific behaviour on each button, I put a Binding for each of the buttons(nothing on the group), and when I need to disable all the group, I then disable buttons one by one.
<Fluent:RibbonGroupBox x:Name="GpRibbonOL" Header="{x:Static p:Resources.NestingLaunchingOrder}">
<Fluent:Button x:Name="DeleteOL" IsEnabled="{Binding EnableDeleteOL}" SizeDefinition="Large" LargeIcon="img\image_delete.png" Header="{x:Static p:Resources.Supprimer}" Click="Supprimer_OF">
<Fluent:Button.ToolTip>
<Fluent:ScreenTip x:Name="ScreenTipDeleteOL" Image="img\image_delete.png" Title="Delete OL" Width="250" Text="Delete element" DisableReason="{Binding EnableEditNestingReason}">
</Fluent:ScreenTip>
</Fluent:Button.ToolTip>
</Fluent:Button>
...
</Fluent:RibbonGroupBox>
ViewModel looks like that, so when I want to Enable/Disable, I just change the tooltip :
private bool enableGpRibbonNesting;
public bool EnableGpRibbonNesting
{
get { return enableGpRibbonNesting; }
set
{
enableGpRibbonNesting = value;
this.NotifyPropertyChanged("EnableGpRibbonNesting");
}
}
private string enableGpRibbonNestingReason;
public string EnableGpRibbonNestingReason
{
get { return enableGpRibbonNestingReason; }
set
{
enableGpRibbonNestingReason = value;
if (value == "")
{
EnableGpRibbonNesting = true;
}
else
{
EnableGpRibbonNesting = false;
}
this.NotifyPropertyChanged("EnableGpRibbonNestingReason");
}
}

Related

Setting Visibility="Collapsed" doesn't hide the Button. Update: Fixed by myself but I want to know the reason for the issue

I am creating a custom transport controls. In that, I have added an AppBarButton. To change the visibility of that I have created a Property for it, but for some reason, it doesn't work. The AppBarButton is always visible.
Code of the Property
//To change Visibility for CompactOverlayButton
public bool IsCompactOverlayButtonVisible
{
get
{
return compactOverlayButton != null && compactOverlayButton.Visibility == Visibility.Visible;
}
set
{
if (compactOverlayButton != null) //To neglect the Visibility check before the Template has been applied
{
compactOverlayButton.Visibility = value ? Visibility.Visible : Visibility.Collapsed;
}
}
}
So I started debugging it. I can't find any error in the C# part, so I set Visibility="Collapsed" for AppBarButton in the XAML part. I am surprised, Even though I set Visibility="Collapsed" the AppBarButton is still visible.
Here is my code in XAML part
<AppBarButton x:Name='CompactOverlayButton'
Style='{StaticResource AppBarButtonStyle}'
MediaTransportControlsHelper.DropoutOrder='17' Visibility="Collapsed">
<AppBarButton.Icon>
<FontIcon Glyph=""/>
</AppBarButton.Icon>
</AppBarButton>
Update:
I found out the line of code which is causing it. It is from the C# part of the page where I have used this CustomMediaTransportControls.
The Line which causing this is
var youtubeUrl = await YouTube.GetVideoUriAsync("QTYVJhy04rs", YouTubeQuality.Quality144P, videoQuality);
I have fixed the issue problem by setting CustomMediaControl.IsCompactOverlayButtonVisible = false; after the above line of code. Still, I want to how the above line is affecting my program. The entire code the been included in the for reference part
For Reference:
Here is my entire code
CustomMediaTransportControls.cs - Derived class from MediaTransportControls
MediaPlayerDictionary.xaml - ResourceDictionary
VideosPage.xaml - C# part of the page where I have used this CustomMediaTransportControls
I am not sure if removing this one line resolved the issue since i had the same issue without this line of code. However i found a workaround for this problem:
Add a Property for the visibility as well as the according listener:
public Visibility CompactOverlayButtonVisibility
{
get { return (Visibility)GetValue(CompactOverlayButtonVisibilityProperty); }
set { SetValue(CompactOverlayButtonVisibilityProperty, value); }
}
public static readonly DependencyProperty CompactOverlayButtonVisibilityProperty =
DependencyProperty.Register(nameof(CompactOverlayButtonVisibility) , typeof(Visibility), typeof(CustomMediaTransportControls), new PropertyMetadata(Visibility.Visible, OnVisibisityChanged));
internal static void OnVisibisityChanged(DependencyObject d, DependencyPropertyChangedEventArgs e){
if (((CustomMediaTransportControls)d).compactOverlayButton != null)
{
if ((Visibility)e.NewValue != Visibility.Visible)
((CustomMediaTransportControls)d).commandBar.PrimaryCommands.Remove(((CustomMediaTransportControls)d).compactOverlayButton);
else if (!((CustomMediaTransportControls)d).commandBar.PrimaryCommands.Contains(((CustomMediaTransportControls)d).compactOverlayButton))
((CustomMediaTransportControls)d).commandBar.PrimaryCommands.Insert(4, ((CustomMediaTransportControls)d).compactOverlayButton);
((CustomMediaTransportControls)d).compactOverlayButton.Visibility = Visibility.Visible;
}
And add the following to your OnApplyTemplateMethod:
commandBar = GetTemplateChild("MediaControlsCommandBar") as CommandBar;
compactOverlayButton = GetTemplateChild("CompactOverlayButton") as AppBarButton;
if (CompactOverlayButtonVisibility != Visibility.Visible)
commandBar.PrimaryCommands.Remove(compactOverlayButton);
else if(!commandBar.PrimaryCommands.Contains(compactOverlayButton))
commandBar.PrimaryCommands.Insert(4, compactOverlayButton);
compactOverlayButton.Visibility = Visibility.Visible;
However you might want to investigate why the Visibility is changed from code despite being set in the xaml code. Maybe this is true for all AppBarButtons maybe not. You could try that out and then look into the relevant sourcecode here. If you found the reason you might figure out a better solution.

IDataErrorInfo not updated

I encountered a problem with the IDataErrorInfo Interface and a wizard I'm currently programming.
The intention of my programm is to ask some Inputs ( usually done with a barcode scanner) and depending on the inputs start a specific sequence.
This is working as intendet. To make sure to catch wrong scans all inputs are check with an event ( OnValueParseFailed) If this event is triggered my current textbox is focused and all text selected:
this.MyWizardViewModel.ValueParseFailed += (s, e) =>
{
switch (e.Parameter)
{
case "ProductionOrder":
this.TextBoxProduction.Focus();
this.TextBoxProduction.SelectAll();
break;
The Interface itself is included this way:
public string this[string name]
{
get
{
string result = null;
if ((name == "ProductionOrder") && (!string.IsNullOrEmpty(this.ProductionOrder)))
{
if (this.System.FirmwareVersion == 0)
result = Lang.Strings.WrongEntry;
}
Its working for the first run. But if the wizard is finished or aborted and run a second time without closing the app, no error message is shown.
The Reset simply returns the app to default values.
public void ResetApplikation()
{
this.System.Clear(); // reset System values
this.ProductionOrder = string.Empty;
this.BmsTypeCode = string.Empty;
this.CellStack1TypeCode = string.Empty;
this.CellClass1 = string.Empty;
this.CellStack2TypeCode = string.Empty;
this.CellClass2 = string.Empty;
this.IsSystemProgrammed = false;
this.IsSystemParameterized = false;
this.MyMachine.Abort(); // reset wizard state
}
While debugging I can see the Interface to be handeled correctly. But no error is displayed.
In XAML the binding is set TwoWay
<TextBox Name="TextBoxProduction" Grid.Row="2" Width="200" Margin="10"
Style="{StaticResource TextBoxNormal}" Loaded="TextBoxProduction_Loaded"
Text="{Binding Path=ProductionOrder, ValidatesOnDataErrors=True,
NotifyOnValidationError=True, Delay=100,
UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" />
I'm using MahApps but as the textbox class is based on the wpf textbox I doubt a bug in this element is the problem. Any suggestions would be great.
Thank you.
The Answer of Domysee helped me.
Implementing INotifyDataErrorInfo instead of IDataErrorInfo was a major change but it fixed the problem!

Silverlight RadComboBox make whole texbox area clickable

Is it possible to make the whole text area of the RadComboBox clickable while having IsEditable=true and ReadOnly=True?
I would just set IsEditable = false but unfortunately I need it to be editable in order to display custom text when something is selected (I have it set so multiple things can be selected and present a list of the selected items). If I disable IsEditable then I lose the .Text attribute and can't set a custom text.
My two best bets would be:
1) somehow apply a style that makes the whole textbar clickable and not just the arrow
2) somehow apply custom text display when IsEditable is set to false.
Unfortunately I don't know how to do either so any help would be nice. Thanks
Edit: This would be ideal, except that we're using Silverlight and not ASP.net
http://demos.telerik.com/aspnet-ajax/combobox/examples/functionality/checkboxes/defaultcs.aspx
This is probably more realistic, just to somehow make the text area clickable so it opens the dropdown menu. Just like the ComboBox on the right, minus being able to type. http://demos.telerik.com/aspnet-ajax/combobox/examples/functionality/comboboxvsdropdownlist/defaultcs.aspx
I can think of several solutions, of varying elegance. Here is one that might be suitable to close your remaining gap between the Arrow-ToggleButton and the Text-Input-Area. And now that I think about it... maybe you can get rid of that rather smelly and fragile side-effect-piggybacking with the OpenDropDownOnFocus property (which will break as soon as a click does not change the focus owner).
Register a MouseLeftButtonDown click handler with the RadComboBox, you can choose to get all events, not only unhandled events. Then we can toggle the DropDown from there. But we don't want to interfere with the Arrow-ToggleButton, therefore we check from where the mouse click originated.
public class MyView : UserControl
{
public MyView()
{
InitializeComponent();
MouseButtonEventHandler handler = OnComboBoxClicked;
radComboBox.AddHandler( UIElement.MouseLeftButtonDownEvent, handler,
handledEventsToo: true );
}
private void OnComboBoxClicked( object sender, MouseButtonEventArgs args )
{
if (!args.Handled ||
!args.IsRoutedEventFromToggleButton(
togglebuttonAncestorToStopTheSearch: (UIElement) sender))
{
ToggleDropDown();
}
}
}
and extension methods for easier use:
public static class ControlExtensions
{
public static bool IsRoutedEventFromToggleButton(
this RoutedEventArgs args,
UIElement togglebuttonAncestorToStopTheSearch )
{
ToggleButton toggleButton = ((UIElement) args.OriginalSource)
.GetAncestor<ToggleButton>( togglebuttonAncestorToStopTheSearch );
return toggleButton != null;
}
public static TAncestor GetAncestor<TAncestor>(
this DependencyObject subElement,
UIElement potentialAncestorToStopTheSearch )
where TAncestor : DependencyObject
{
DependencyObject parent;
for (DependencyObject subControl = subElement; subControl != null;
subControl = parent)
{
if (subControl is TAncestor) return (TAncestor) subControl;
if (object.ReferenceEquals( subControl,
potentialAncestorToStopTheSearch )) return null;
parent = VisualTreeHelper.GetParent( subControl );
if (parent == null)
{
FrameworkElement element = subControl as FrameworkElement;
if (element != null)
{
parent = element.Parent;
}
}
}
return null;
}
}
I ended up finding a multiselectcombobox that someone else implemented here:
http://www.telerik.com/support/code-library/a-multiselect-combobox
I didn't need the whole combobox itself since we already had one implemented so I just looked at how the person was displaying a custom message while the combo box IsEditable was set to false.
After looking at that code for a while and seeing how I can make it work for me, I put
<ucControls:RadComboBox.SelectionBoxTemplate>
<DataTemplate>
<TextBlock Text="{Binding Text,ElementName=RadCombo}" />
</DataTemplate>
</ucControls:RadComboBox.SelectionBoxTemplate>
inside the XAML of our own custom MultiSelectComboBox. (RadCombo being the name of the particular control that I wanted the Text to be linked to)
<ucControls:RadComboBox
x:Name="RadCombo"
Text=""
........
<ucControls:RadComboBox.SelectionBoxTemplate>
<DataTemplate>
<TextBlock Text="{Binding Text,ElementName=RadCombo}" />
</DataTemplate>
</ucControls:RadComboBox.SelectionBoxTemplate>
.......
</ucControls:RadComboBox>
Using the built in SelectionBoxTemplate, this basically just added a TextBlock overlay, and the content was bound to the RadComboBox's own Text, so when we would set the Text of the RadComboBox, the TextBlock would update itself.
This was the most effective way for us to do it because it required minimal code changes, and no structure changes since we already had all the code in place for checking boxes and setting a custom text.
Hope this helps someone, best of luck!

ContentPresenter not updating display correctly

In my program's main window I have a TreeView and a ContentPresenter. The display of the ContentPresenter is determined by what node is selected in the TreeView.
The name of one of my nodes is allowed to be changed by the user via contentMenu. All the user has to do is right click the node and select the new name out of the choices. The ContentPresenter is supposed to have a null display until the user chooses a name for the node.
The problem occurs when a new name is selected from the contentMenu. The ContentPresenter's display changes, like it should, but only after the user selects a different node (changing the display), and then re-selects the original node.
How do I make it so that the display on the ContentPresenter changes right when the TreeView node's name is changed?
TreeViewViewModel:
public class TreeViewViewModel : PropertyChangedBase
{
public TreeViewViewModel()
{
Node = new Node() { NodeName = "Blank", NodeDataModel = new NodeModel(),
Commands = { new Command(nodeType_name1), new Command(nodeType_name2) } };
}
//These functions call to the NodeName property in the TreeView's Data Model
private void nodeType_name1()
{
Node.NodeName = "Name1";
}
private void nodeType_name2()
{
Node.NodeName = "Name2";
}
}
XAML for MainWindow:
<!-- Tree view items & Functions -->
<TreeView Name="Tree_One" ItemsSource="{Binding DataTree.Data}" ... >
<TreeView.Resources>
<SolidColorBrush Color="LightSkyBlue" x:Key="{x:Static SystemColors.HighlightBrushKey}" />
</TreeView.Resources>
</TreeView>
<!--- Left Widget -->
<ContentPresenter Content="{Binding LeftWidget}" />
MainWindowViewModel:
public class MainWindowViewModel : PropertyChangedBase
{
private TreeViewViewModel _dataTree;
public MainWindowViewModel()
{
_dataTree = new TreeViewViewModel();
}
public TreeViewViewModel DataTree { ... }
//This function is in charge of changing the display of the ContentPresenter
// I think that my problem can probably be solved by doing something here
public void ChangeViews()
{
if (_dataTree.SelectedItem is Node)
{
var _node = _dataTree.SelectedItem as Node;
var nodeViewModel = new NodeViewModel(_node.NodeDataModel);
if (_node.NodeName== "Unknown")
LeftWidget = null; //This is the Content Presenter **
if (_node.NodeName == "Name1")
{
LeftWidget = nodeViewModel;
}
if (_node.NodeName == "Name2") {...}
}
}
}
Duh, thats a alot of code and its pretty difficult to understand what you up to since you seem to have controls in your ViewModel.
Or at least it looks to me that you have them in ViewModel. That is not very MVVM-alike my friend. :)
"The problem occurs when a new name is selected from the contentMenu. The ContentPresenter's display changes, like it should, but only after the user selects a different node (changing the display), and then re-selects the original node."
The property changed is not being fired because the new selected value is equal to the old one.
Pretty obvious, right?... no property was actually changed
But why do you want the ContentPresenter to update itself with the value that it already has?
You said when you select a node the ContentPresenter displays it properly and when you re-select the same the ContentPresenter is not doing anything.
Its not doing anything because it think it doesnt need to. Which is true.
So the question is why would you make ContentPresenter force to refresh on each value no matter if old value is the same as new one?
Though if you want to hack/trick a little bit, you can always set ContentPresenter's Content to null before you assign another value. :)
However, post us more code and we will be able to provide you a better solution to your issue.
I was able to fix this issue by calling ChangeViews(); in my MainWindowViewModel from my TreeViewViewModel. I did this by using a delegate property in the TVVM, and adding it to my MWVM. By doing this, the display is updated whenever ChangeViews(); is called.
This is the answer that I used.

silverlight Binding from VM collection to View not working need some help

I know I am missing something here and I could use a pointer. Within a project I have an expander control when this control is clicked it makes a RIA call to a POCO within my project to retreive a second set of data. I am using the SimpleMVVM toolkit here so please let me know if I need to expand on any additional areas.
Within the xaml the expander is laid out as
<toolkit:Expander Header="Name" Style="{StaticResource DetailExpanderSytle}" >
<i:Interaction.Triggers>
<i:EventTrigger EventName="Expanded">
<ei:CallMethodAction
TargetObject="{Binding Source={StaticResource vm}}"
MethodName="showWarrantNameDetail"/>
</i:EventTrigger>
</i:Interaction.Triggers>
<StackPanel Orientation="Vertical">
<sdk:DataGrid AutoGenerateColumns="true" ItemsSource="{Binding NameResult}" AlternatingRowBackground="Gainsboro" HorizontalAlignment="Stretch" MaxHeight="200">
</sdk:DataGrid>
<local:NameContainer DataContext="{Binding}" />
</StackPanel>
</toolkit:Expander>
I am using the expression Dll coupled with Simple MVVM to get at the methods in the view model vs commands.
Within the view model I have the following code
public void showWarrantNameDetail()
{
//set flags
IsBusy = true;
CanDo = false;
EntityQuery<WarrantNameDataView> query = App.cdContext.GetWarrantNameDataViewsQuery().Where(a => a.PrimaryObjectId == Convert.ToInt32(RecID));
Action<LoadOperation<WarrantNameDataView>> completeProcessing = delegate(LoadOperation<WarrantNameDataView> loadOp)
{
if (!loadOp.HasError)
{
processWarrantNames(loadOp.Entities);
}
else
{
Exception error = loadOp.Error;
}
};
LoadOperation<WarrantNameDataView> loadOperation = App.cdContext.Load(query, completeProcessing, false);
}
private void processWarrantNames(IEnumerable<WarrantNameDataView> entities)
{
ObservableCollection<WarrantNameDataView> NameResult = new ObservableCollection<WarrantNameDataView>(entities);
//we're done
IsBusy = false;
CanDo = true;
}
When I set a break on the processWarrantName I can see the NameResult is set to X number of returns. However within the view the datagrid does not get populated with anything?
Can anyone help me understand what I need to do with the bindings to get the gridview to populate? Other areas of the form which are bound to other collections show data so I know I have the data context of the view set correctly. I've tried both Data context as well as Items Source and no return?
When I set a break on the code the collection is returned as follows so I can see that data is being returned. Any suggestions on what I am missing I would greatly appreciate it.
With regards to the page datacontext I am setting it in the code behind as follows:
var WarrantDetailViewModel = ((ViewModelLocator)App.Current.Resources["Locator"]).WarrantDetailViewModel;
this.DataContext = WarrantDetailViewModel;
this.Resources.Add("vm", WarrantDetailViewModel);
Thanks in advance for any suggestions.
Make ObservableCollection<WarrantNameDataView> NameResult a public property of your ViewModel class. Your view will not be able to bind to something that has a private method scope (or public method scope, or private member scope).
//declaration
public ObservableCollection<WarrantNameDataView> NameResult { get; set }
//in the ViewModel constructor do this
NameResult = new ObservableCollection<WarrantNameDataView>();
//then replace the original line in your method with:
//EDIT: ObservableCollection has no AddRange. Either loop through
//entities and add them to the collection or see OP's answer.
//NameResult.AddRange(entities);
If processWarrantNames gets called more than once, you might need to call NameResult.Clear() before calling AddRange() adding to the collection.
Phil was correct in setting the property to public. One note I'll add is there is no AddRange property in SL or ObservableCollection class that I could find. I was able to assign the entities to the OC using the following code
private ObservableCollection<WarrantNameDataView> warrantNameResult;
public ObservableCollection<WarrantNameDataView> WarrantNameResult
{
get { return warrantNameResult; }
set
{
warrantNameResult = value;
NotifyPropertyChanged(vm => vm.WarrantNameResult);
}
}
and then within the return method
WarrantNameResult = new ObservableCollection<WarrantNameDataView>(entities);
This worked and passed to the UI the collection of data.

Categories

Resources