|
How would this work in MVVM? As the application has been built using this design pattern.
|
|
|
|
|
The view model should be bound to the datacontext, so the SelectedItem property should get it.
The funniest thing about this particular signature is that by the time you realise it doesn't say anything it's too late to stop reading it.
|
|
|
|
|
I would use linq to identify the record to be deleted and then remove it from the list
classname Instance = Listname.Where(x=>x.Field = Criteria).FirstOrDefault();
if(Instance !=Null)
{ListName.Remove(Instance);}
Never underestimate the power of human stupidity
RAH
|
|
|
|
|
How would this work in MVVM? As the application has been built using this design pattern.
|
|
|
|
|
Member 2972992 wrote: As the application has been built using this design pattern
This indicates it was not built by you and it seem you have limited exposure to MVVM or Silverlight. It is going to be a little difficult to explain in a forum post, you have a learning curve in front of you that is going to include at least 1 book!
Never underestimate the power of human stupidity
RAH
|
|
|
|
|
I have a MVVM application that has a MainWindow.xaml that defines the main window. The main window has a ribbon control and a tabbed MDI interface similiar to Visual Studio. The tabs are implemented in UserControl.xaml. So, obviously, I can have a bunch of UserControl instances.
Now, I want to add a button to the ribbon, but the button is going to operate on the active UserControl.xaml view model.
So the question is what is the best way to wire that up?
I have a few ideas, but they all seem bad.
1) have a static command class that defines the ICommands and somehow map that into the command bindings of the view and redirect into the VM. Not really sure how all that is going to wire up.
2) have UserControlVM expose a static command that takes an instance as the param and have MainWindow.xaml bind the button to that static command and pass in the active window.
Any other ideas?
|
|
|
|
|
You're gonna love this. Fellow WPF Disciple, Kent Boogaart, has created a command system for just such an eventuality. It's called the ActiveAwareCommand[^] and it's very cool.
|
|
|
|
|
Thanks, I'll take a look.
|
|
|
|
|
I am very new to WPF and I have taken over a WPF project from someone else.
Problem I have is removing a rows from two datagrids. To expand on this, the UI works as follows; there are 3 datagrid; the first column (a Combobox) on each of the three datagrids are bound to the same data source. However, the columns on the other two datagrids (also comboboxes) their values depends upon whatever the user selects as their selected item in the first combobox, and this works in the viewmodel layer. All of this works fine, but problem comes with removing rows.
The issue I have is this, if I remove a row in the first datagrid, and lets say this row has the value of "X", this gets deleted. If this value appears in a row in other two datagrids, the column in the other two datagrids gets removed but not the row themselves. So, my question is, how do remove a row or rows from a datagrid based upon a value from another datagrid?
Thanks
|
|
|
|
|
I need a function to return something that can either be System.Windows.Controls.Control or System.Windows.Controls.StackPanel.
Ideally it should be an interface thats implemented by both or a baseclass of both of them (I hate using object for this purpose)
The likes of UIElement etc seem to be exclusive to one of 'em only.
Any ideas?
|
|
|
|
|
They both derive from FrameworkElement. If you need to, you could hook into that.
|
|
|
|
|
I always try and use the Object Explorer to figure out common inherited parent classes / interfaces.
The funniest thing about this particular signature is that by the time you realise it doesn't say anything it's too late to stop reading it.
|
|
|
|
|
cethie wrote: The likes of UIElement etc seem to be exclusive to one of 'em only.
All the WPF/Silverlight elements are UIElements...not sure where you are seeing exclusiveness. FrameworkElement derives from UIElement, and can be used as well as Pete mentioned.
Mark Salsbery
Microsoft MVP - Visual C++
|
|
|
|
|
Hi everyone, I'm new to WPF. I'd appreciate your advice on what should be simple functionality.
I'm building a wizard and am basing my code on the following example:
Creating an Internationalized Wizard in WPF[^]
Rather than using an Items Control with a Data Template of CheckBoxes I want to use an Items Control with a Data Template of ListBoxItems all wrapped in a ListBox.
I have created the following XAML
<ListBox>
<ItemsControl
ItemsSource="{Binding Path=AvailablePitchbookChartFamily}"
Width="100">
<ItemsControl.ItemTemplate>
<DataTemplate>
<ListBoxItem
Content="{Binding Path=DisplayName}"
IsSelected="{Binding Path=IsSelected}"
/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ListBox>
The collection AvailablePitchbookChartFamily is of Type OptionViewModel the full implementation of this class is displayed at the end of this post. The OptionViewModel class allows me to assign display properties and event handlers to each item in the collection.
The problem I am having is that when I have bound the collection of OptionViewModel to my Items Control the ListBox that wraps the Items Control does not function. What I am trying to achieve is that when you select an item in ListBox the PropertyChanged event handler for the ListBoxItem would fire allowing me to update the properties of the object I am modelling in the business logic. However currently all of the required ListBox items are displayed in the ListBox but they are not selectable and the PropertyChanged event is not fired when you attempt to select them.
I'm guessing that the OptionViewModel type in its current form is not going to work with a ListBox but I would be very happy if someone can prove me wrong.
Here's the relevant code behind for the ViewModel.
Private _objAvailablePitchbookChartFamily As ReadOnlyCollection(Of OptionViewModel(Of enumPitchbookChartFamily))
Public ReadOnly Property AvailablePitchbookChartFamily() As ReadOnlyCollection(Of OptionViewModel(Of enumPitchbookChartFamily))
Get
If _objAvailablePitchbookChartFamily Is Nothing Then
CreateAvailablePitchbookChartFamily()
End If
Return _objAvailablePitchbookChartFamily
End Get
End Property
Private Sub CreateAvailablePitchbookChartFamily()
' We can't bind directly to the enum as we need to support multiple languages
' Map the enum to the resource file string here
Dim obj As New List(Of OptionViewModel(Of enumPitchbookChartFamily))
With obj
.Add(New OptionViewModel(Of enumPitchbookChartFamily)(My.Resources.Strings.ChartFamily_Area, enumPitchbookChartFamily.Area))
.Add(New OptionViewModel(Of enumPitchbookChartFamily)(My.Resources.Strings.ChartFamily_Bar, enumPitchbookChartFamily.Bar))
.Add(New OptionViewModel(Of enumPitchbookChartFamily)(My.Resources.Strings.ChartFamily_Bubble, enumPitchbookChartFamily.Bubble))
.Add(New OptionViewModel(Of enumPitchbookChartFamily)(My.Resources.Strings.ChartFamily_Column, enumPitchbookChartFamily.Column))
.Add(New OptionViewModel(Of enumPitchbookChartFamily)(My.Resources.Strings.ChartFamily_Line, enumPitchbookChartFamily.Line))
.Add(New OptionViewModel(Of enumPitchbookChartFamily)(My.Resources.Strings.ChartFamily_Pie, enumPitchbookChartFamily.Pie))
.Add(New OptionViewModel(Of enumPitchbookChartFamily)(My.Resources.Strings.ChartFamily_Scatter, enumPitchbookChartFamily.Scatter))
.Add(New OptionViewModel(Of enumPitchbookChartFamily)(My.Resources.Strings.ChartFamily_Stock, enumPitchbookChartFamily.Stock))
.Add(New OptionViewModel(Of enumPitchbookChartFamily)(My.Resources.Strings.ChartFamily_Waterfall, enumPitchbookChartFamily.Waterfall))
End With
For Each objOption As OptionViewModel(Of enumPitchbookChartFamily) In obj
' Set the default value assigned in in Model for display in the view
If Me.PitchbookChart.ChartFamily = objOption.GetValue Then
objOption.IsSelected = True
End If
AddHandler objOption.PropertyChanged, AddressOf OnPitchbookChartFamilySelectionChanged
Next
obj.Sort()
_objAvailablePitchbookChartFamily = New ReadOnlyCollection(Of OptionViewModel(Of enumPitchbookChartFamily))(obj)
End Sub
Here is the full implementation of OptionViewModel Class
Imports System.ComponentModel
Public Class OptionViewModel(Of TValue)
Implements INotifyPropertyChanged
Implements IComparable(Of OptionViewModel(Of TValue))
#Region " Declarations "
Private Const UNSET_SORT_VALUE As Integer = Integer.MinValue
Private _bolIsSelected As Boolean = False
Private _intSortValue As Integer = Integer.MinValue
Private _objValue As TValue
Private _strDisplayName As String = String.Empty
#End Region
#Region " Properties "
Public ReadOnly Property DisplayName() As String
Get
Return _strDisplayName
End Get
End Property
Public Property IsSelected() As Boolean
Get
Return _bolIsSelected
End Get
Set(ByVal Value As Boolean)
_bolIsSelected = Value
OnPropertyChanged("IsSelected")
End Set
End Property
Public ReadOnly Property SortValue() As Integer
Get
Return _intSortValue
End Get
End Property
#End Region
#Region " Constructors "
Public Sub New(ByVal strDisplayName As String, ByVal objValue As TValue)
_strDisplayName = strDisplayName
_objValue = objValue
End Sub
Public Sub New(ByVal strDisplayName As String, ByVal objValue As TValue, ByVal intSortValue As Integer)
_strDisplayName = strDisplayName
_objValue = objValue
_intSortValue = intSortValue
End Sub
#End Region
#Region " Events "
Public Event PropertyChanged As PropertyChangedEventHandler Implements System.ComponentModel.INotifyPropertyChanged.PropertyChanged
#End Region
#Region " Methods "
Public Function CompareTo(ByVal other As OptionViewModel(Of TValue)) As Integer Implements System.IComparable(Of OptionViewModel(Of TValue)).CompareTo
If other Is Nothing Then
Return -1
ElseIf Me.SortValue = UNSET_SORT_VALUE AndAlso other.SortValue = UNSET_SORT_VALUE Then
Return Me.DisplayName.CompareTo(other.DisplayName)
ElseIf Me.SortValue <> UNSET_SORT_VALUE AndAlso other.SortValue <> UNSET_SORT_VALUE Then
Return Me.SortValue.CompareTo(other.SortValue)
ElseIf Me.SortValue <> UNSET_SORT_VALUE AndAlso other.SortValue = UNSET_SORT_VALUE Then
Return -1
Else
Return +1
End If
End Function
Public Function GetValue() As TValue
Return _objValue
End Function
Protected Sub OnPropertyChanged(ByVal strPropertyName As String)
Dim handler As PropertyChangedEventHandler = Me.PropertyChangedEvent
If handler IsNot Nothing Then
handler.Invoke(Me, New PropertyChangedEventArgs(strPropertyName))
End If
End Sub
#End Region
End Class
|
|
|
|
|
I didn't read your entire post (waaay too long), but I think your issue is that you are putting an ItemsControl inside of your list box and then ListBoxItems inside of the ItemsControls. Thats not quite right. Set ItemsSource on the ListBox and template only the ListBoxItems themselves. Everything will work that way.
|
|
|
|
|
Hi thanks for your reply
Yes my post is too long and I did read the posting guidelines before posting but how are good people like you supposed to help without all of the information?
Yes I can make the listbox look and function as I would expect a listbox to function with this.
<ListBox
ItemsSource="{Binding Path=AvailablePitchbookChartFamily}"
DisplayMemberPath="DisplayName"
>
</ListBox>
The issue is that the type OptionViewModel implements INotifyPropertyChanged. A collection of this type is bound to my Listbox. However the act of changing a selected item does not fire the PropertyChanged event and therefore doesn't update the underlying business object being modelled. I've been trying to structure the listbox in a way that it looks just like a listbox but the PropertyChanged event does fire when a listbox item is selected/deselected. My lack of WPF knowledge is currently stopping me from achieving this.
Anyway I'll keep improving my knowledge. I think I'll end up doing something with the IObservable interface.
Thanks for your help
|
|
|
|
|
The ListBox fires a SelectionChanged event when the selection changes, so you can do what you want in 2 ways... 1) bind the SelectedItem to a property in your VM using 2 way binding, or 2) tie the SelectionChanged event to a command in your VM so your command handler gets called when the selection changes
#2 is a bit trickier to implement, both are acceptable. #2 is preferable though when you want to do something when the selection changes.
|
|
|
|
|
I have a View and ViewModel. View has a TreeView in it. I want to detect when the user double clicks on a **TreeViewItem**, not the actual tree itself. Whats the common way to do this? I want to somehow bind that event to a RelayCommand in the ViewModel.
I'm familiar with System.Windows.Interactivity and Interaction.Triggers, and that works fine for events coming from the TreeView itself, but it doesn't seem possible to put it in a TreeViewItem style, etc or trap events from TreeViewItem.
I had a vague idea, but I'll hold that until I get some responses... it seems kind of hacky .
|
|
|
|
|
So you have one half of the answer with using the EventToCommand behavior to hook up to the relevant command. The other half depends on how you populate the TreeView - if you use the TreeView.ItemTemplate, then you can attach it in there, e.g.
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Countries}">
<TextBlock Text="{Binding Name}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseDoubleClick">
<i:InvokeCommandAction CommandName="DoubleClickCommand" CommandParameter="{Binding Name}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</TextBlock>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
|
|
|
|
|
Tricky, tricky .
|
|
|
|
|
That's me - Captain MacTricky of the Clan Tricky.
|
|
|
|
|
Hmm... this doesn't actually work. Unless I'm missing something obvious.
<TreeView ItemsSource="{Binding StateCountyItems}" FocusVisualStyle="{x:Null}" BorderThickness="0,0,0,0">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Value}">
<TextBlock Text="{Binding Key}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseDoubleClick">
<i:InvokeCommandAction CommandName="Test" />
</i:EventTrigger>
</i:Interaction.Triggers>
</TextBlock>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
My ViewModel has:
public RelayCommand Test
{
get
{
if (_test == null)
_test = new RelayCommand(t);
return _test;
}
}
private void t()
{
}
With that XAML exactly, the Test getter is never even called. I changed CommandName to Command="{Binding ElementName=g, Path=DataContext.Test}"
g is the window that has its DataContext set... I'll of course clean up the names later lol... when I change it to that, NOW the Test getter is called, BUT void t() is never called when I double click.
any ideas?
|
|
|
|
|
Hmm... when I change the event to PreviewMouseMove, then the handler gets called, but not for MouseDoubleClick. Works for PreviewMouseLeftButtonDown and MouseLeftButtonDown and other events. Guess the double click is getting eaten. Son of a...
|
|
|
|
|
Hmmm. That's not great. I suspect the TreeView is consuming it for its own purposes then (e.g. opening/closing nodes).
|
|
|
|
|
I was able to trap the MouseLeftButtonDown and check MouseButtonEventArgs.ClickCount == 2. Good enough I suppose.
|
|
|
|