Programmatically Adding Buttons in MVVM but Command doesn't work - wpf

I'm trying to add buttons dynamically and it's work but command doesn't work.
I'm getting error
ItemTemplate and ItemTemplateSelector are ignored for items already of the ItemsControl's container type; Type='RadRibbonButton'
<telerik:RadRibbonGroup>
...
<telerik:RadRibbonGroup.DataContext>
<vm:Group1/>
</telerik:RadRibbonGroup.DataContext>
<ItemsControl ItemsSource="{Binding ButtonsCollection}" >
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button Content="{Binding}" Command="{Binding DataContext.ButtonCommand, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type telerik:RadRibbonGroup}}}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</telerik:RadRibbonGroup>
ButtonCommand= new DelegateCommand(ExecuteCommand);
private void ExecuteCommand()
{
...
}

Check that it does reach the command in debug mode.
Is your ButtonsCollection is dependency property? do you raise its change?
You are not supposed to add actual buttons to your buttons collection, thats is not pure mvvm. you need to create the buttons in a data template, and in the collection you need to create the properties like the button's content etc.
If you still insist creating actual buttons, i think that templating "" won't work. Try "

It doesn't reach
ObservableCollection of buttons(and I can see the buttons in the view)
3.I should create and add buttons to collection runtime(There are special logic behind this).In constructor I create command

Related

WPF: Can I have multiple ItemsControls with different ItemsSources?

In my WPF App, I want to have several items that are generated by the user on runtime. These are from different classes and hence, my original idea was to add them to different Observable Collections and then use them as ItemsSources od different ItemsControls. However, WPF gives me the error System.InvalidOperationException: Items collection must be empty before using ItemsSource. I'm not a WPF expert, but the answer to THIS SO question seems to indicate that I can only have 1 ItemsControl.
THIS SO question indicates that maybe I should use the CompositeCollection Class, but unlike in the cited question, I have several completely different Observable Collections for completely different tasks.
Here is the relevant part of my XAML.CS with two Collections: 1 of a custom Interface type and 1 of custom Class type
public MainWindow()
{
InitializeComponent();
DefaultWindowDefinition.ItemsSource = ProcessElements = new ObservableCollection<IProcessSimulator>();
PathControl.ItemsSource = PathElements = new ObservableCollection<VisualPath>();
}
And here is the relevant part of the XAML I tried to use:
<Grid x:Name="MainGrid"
Background="{StaticResource Alternating}"
MouseLeftButtonUp="grid_MouseLeftButtonUp"
ShowGridLines="True">
<ItemsControl Name="DefaultWindowDefinition"
ItemsSource="{Binding ProcessElements}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<!--HERE IS A LONG LIST OF ELEMENTS-->
</DataTemplate>
</ItemsControl.ItemTemplate>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<!--TEMPLATE FOR THE 1ST ITEMSCONTROL-->
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemContainerStyle>
<Style>
<!--STYLE PROPERTIES FOR THE 1ST ITEMSCONTROL-->
</Style>
</ItemsControl.ItemContainerStyle>
</ItemsControl>
<ItemsControl Name="PathControl"
ItemsSource="{Binding PathElements}">
<DataTemplate>
<!--HERE IS A LIST OF OTHER TYPE OFELEMENTS-->
</DataTemplate>
</ItemsControl>
</Grid>
How should I approach this problem or rather, what C#/WPF element should I use? A reference and some words of simple explanation is more than enough, I can google the rest myself, I just don't know, what to look for really.
You should set the ItemTemplate property of the "PathControl" to your DataTemplate:
<ItemsControl Name="PathControl" ItemsSource="{Binding PathElements}">
<ItemsControl.ItemTemplate> <!-- NOTE THIS -->
<DataTemplate>
<!--HERE IS A LIST OF OTHER TYPE OFELEMENTS-->
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
If you omit the <ItemsControl.ItemTemplate> element, you are adding a DataTemplate to the Items collection of the ItemsControl and you can't also set its ItemsSource property.
Trying to do so will results in an System.InvalidOperationException exception being thrown with the error message you are getting.
It is perfectly fine for several ItemsControl to bind to the same source collection.
It seems like you are setting the ItemsSource twice. Once in the code behind and once in the XAML. Remove the code behind that sets the Items source and just initialize the observable collections. The XAML should take care of binding to the collections.

DataTemplate is reevaluated on resize of ItemsControl

I found some unexpected behavior in my WPF program. I have a DataTemplate to visualize my data in an ItemsControl.
<ItemsControl ItemsSource="{Binding All}" >
<ItemsControl.ItemTemplate>
<DataTemplate>
<Result:ResultItem/>
</DataTemplate>
</ItemsControl.ItemTemplate>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WPFLibrary:MyPanel Rows="2" MinRows="4" MaxColumns="2" IsItemsHost="true" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
The strange thing is that the ResultItem view is newly created every time MyPanels MeasureOverride is called and hence calls Measure of its childs.
Is there a way to "force" WPf to reuse the view?
Thank in advance
My mistake. The problem was that every time you create a new ObservableCollection the whole view is updated even if the content is not changed at all.

Image binding works in Image not in ItemsControl

I am a bit baffled here. I have a List<BitmapImage> in a Viewmodel that is populating. I am trying to display the list on the view with an ItemsControl, but the Images don't show up. Oddly, I can access the same collection and get an image to display if I am using an Image tag.
<ItemsControl ItemsSource="{Binding Path=Images}" MinHeight="80">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Image Source="{Binding}" MinWidth="80" MinHeight="80" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<Image HorizontalAlignment="Left" Name="image1" Stretch="Uniform" VerticalAlignment="Top" Source="{Binding Path=Images[0]}" MinHeight="80" MaxHeight="200" />
Note that they both point to Images. The Image shows up, the ItemsControl stays empty. What is going on?
You'll solve this by using an ObservableCollection as opposed to a List. The ItemsControl isn't going to rebind on the change notification of a List. You won't have to worry about explicitly calling the change notification for the List either if you use an ObservableCollection.
I was able to replicate your scenario and simply using an ObservableCollection solves the issue. As to why: http://msdn.microsoft.com/en-us/library/system.componentmodel.inotifypropertychanged.aspx
Specifically, see this quote in the Remarks section:
For change notification to occur in a binding between a bound client and a data source, your bound type should either: Implement the INotifyPropertyChanged interface (preferred). Provide a change event for each property of the bound type. Do not do both.

Error when Databinding with mode=twoway

All,
I'm pounding my head against the wall here. What I need is simple, and I'm sure there is a simple answer, but I can't seem to find it.
Situation: I have a Silver light 4.0 app and I'm currently binding a list of strings to an Items control. In the data template for that I have a simple text box that I was doing very basic Binding "{Binding}". I need to update the binding to be twoway so the edits are automatically pushed back to my datacontext.
Here is the Items control before I update the binding:
<ItemsControl x:Name="spLiftHeader" ItemsSource="{Binding Path=WeekLabels}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel x:Name="spLiftHeader" Orientation="Horizontal" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
**<TextBox x:Name="txtWeekLbl" Text="{Binding}" Foreground="Black" Width="125" TextAlignment="Center"/>**
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
Here is the items control after the binding change:
<ItemsControl x:Name="spLiftHeader" ItemsSource="{Binding Path=WeekLabels}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel x:Name="spLiftHeader" Orientation="Horizontal" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
**<TextBox x:Name="txtWeekLbl" Text="{Binding Mode=TwoWay}" Foreground="Black" Width="125" TextAlignment="Center"/>**
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
I've just simply added the "Mode=TwoWay" to the binding.
After updating that, I get the amazingly useless error 4004
"System.Windows.Markup.XamlParseException: Provide value on 'System.Windows.Data.Binding' threw an exception" and the Line/Position reference points right do my updated Binding.
How does one add the Two Way mode to the simple binding?
Thanks in advance.
Nick
Two-way binding to an entire object (a string in this case) makes no sense to Silverlight so it is correct to throw an exception. Shame it is not a more useful error message :)
When there is no Path in the binding the ItemsControl can fetch a value using Object.ToString(), but where will it store the result back? It can't replace the string as that would require placing a new string object back in the collection. Two-way binding is done via reflection against a property of an object.
Instead of a simple list of strings, use a list of some new object that contains a string property and explicitly bind to that property. It will make everything a lot easier. (Make sure your new class and property implement INotifyPropertyChanged).
I am not 100% sure, but I don't think the the Mode=TwoWay should be set in the TextBox itself.
If that doesn't work, try it on both. However, in either case do not use List<T> as a data source behind that items control. Lists do not fire changed event when one of its items has changed. Use ObservableCollection<T> (from the System.Collections.ObjectModel namespace) instead of the List<T>

StackPanel not updating

I am having an issue with a directly bound ObservableCollection not updating a StackPanel when new items are added. Any initial items show up correctly. Only items that are added later on fail to display.
XAML:
<ItemsControl x:Name="ImageTable" ItemsSource="{Binding Path=SystemObjectViewItems, Converter={StaticResource UIElementWrapper}}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid>
<ContentPresenter Content="{Binding Path=Value.View}"/>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
I am using Prism MVVM so I am binding to my ViewModel which has a property:
public ObservableCollection<SystemObjectViewPresentationModel> SystemObjectViewItems {get; set; }
The basic converter and binding are working as can be demonstrated by the fact that my initial item displays correctly. It’s only items that are added to the collection after initial binding that do not show up.
Any ideas?
Thanks,
Rick
I'm going to take a wild guess and say it's the StaticResource you're using.
If you're not returning an ObservableCollection from it and you're not binding it to watch the original ObservableCollection changes it won't work.
Can you post the code to the converter?

Resources