|
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.
|
|
|
|
|
|
Pete O'Hanlon wrote: Ouch. I hate hacks.
And you work with MS technology. hic!
Never underestimate the power of human stupidity
RAH
|
|
|
|
|
Don't see how it's that big of a hack anyways... if the treeview is eating the message, there isn't any other way .
|
|
|
|
|
POHs words were innacurate, I'd call it a work around, its what we do, every framework has shortcomings and it is up to us to work around them to achieve our requirements. Kludge is another valid description, something that works but you are not happy with the way it does it. Elegant on the other hand is what we aspire to!
Never underestimate the power of human stupidity
RAH
|
|
|
|
|
Mycroft Holmes wrote: Kludge is another valid description, something that works but you are not happy
with the way it does it
Or, to put it another way, a hack. So my words were accurate.
|
|
|
|
|
It's a hack, because you don't have any chance to deal with the message you want to. It's not a criticism of your code - just that you shouldn't have to do that. It's at odds with the templated nature of WPF because while you can restyle the UI, you can't restyle the behaviour of the interactions without having to work round it. So, it's a hack.
|
|
|
|
|
hello,
i'm working in wpf application
and using pages
i'm show this pages in frame control
all my page opening in this frame
my questions
how close a page and delete it in navigation from frame
how clear my pages from frame control
Greeting
sayed eltokhy
hello every body
i'm sayed from in egypt
i like vb.net
|
|
|
|
|
I apologise if I haven't quite understood your requirements here, but are you trying to remove the journal entry? If so, you can use NavigationService.RemoveBackEntry to remove a page from the navigation journal.
|
|
|
|
|
I'm finally getting around to trying to learn WPF anyone know of a good resource site to start learning from?
Lobster Thermidor aux crevettes with a Mornay sauce, served in a Provençale manner with shallots and aubergines, garnished with truffle pate, brandy and a fried egg on top and Spam - Monty Python Spam Sketch
|
|
|
|
|
Try here
Lists the blogs of the masters of WPF....sort of... and a couple of CPians that I don't know why are there.....
You know I'm kidding: Pete and Sacha
"Whether you think you can, or you think you can't--either way, you are right." — Henry Ford
"When I waste my time, I only use the best, Code Project...don't leave home without it." — Slacker007
|
|
|
|