I have some generic code that takes a dictionary with unknown generic types and returns all KeyValuePairs with keys that match a specific condition. The problem I have is that I cannot iterate through the collection of KeyValuePairs because that would require code like...
For Each o As KeyValuePair(Of T1, T2) In IDict
For Each o As KeyValuePair(Of Object, Object) In IDict
For Each o As KeyValuePair(Of Object, Object) In IDict.Cast(Of KeyValuePair(Of Object, Object))
There is the option to iterate over a DictionaryEntry collection which does not require me to know the generic types at design time
For Each o As DictionaryEntry In IDict
Now I can examine the keys and values but I can't find a way to convert the DictionaryEntry back to the equivalent KeyValuePair. But I can track the index of the current DictionaryEntry and use IDict.AsQueryable(index) to get the matching KeyValuePair.
Here's an example in Visual Basic and WPF. Just click the [Find Y] button.
Start a Visual Basic WPF application using .Net Framework.
<Window x:Class="MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:GetKeyValuePair"
DataContext="{Binding RelativeSource={RelativeSource Self}}"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Window.Resources>
<RoutedCommand x:Key="FindYCommand"/>
</Window.Resources>
<Window.CommandBindings>
<CommandBinding Command="{StaticResource FindYCommand}" Executed="FindY_Executed"/>
</Window.CommandBindings>
<StackPanel Orientation="Horizontal" Height="22">
<ComboBox ItemsSource="{Binding TheDictionary}"
SelectedItem="{Binding TheSelection}"
DisplayMemberPath="Key" Width="100"/>
<Button Content="Find Y" Command="{StaticResource FindYCommand}"/>
</StackPanel>
</Window>
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:GetKeyValuePair"
DataContext="{Binding RelativeSource={RelativeSource Self}}"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Window.Resources>
<RoutedCommand x:Key="FindYCommand"/>
</Window.Resources>
<Window.CommandBindings>
<CommandBinding Command="{StaticResource FindYCommand}" Executed="FindY_Executed"/>
</Window.CommandBindings>
<StackPanel Orientation="Horizontal" Height="22">
<ComboBox ItemsSource="{Binding TheDictionary}"
SelectedItem="{Binding TheSelection}"
DisplayMemberPath="Key" Width="100"/>
<Button Content="Find Y" Command="{StaticResource FindYCommand}"/>
</StackPanel>
</Window>
-------------------------------------------------------------------------------
Imports
System.ComponentModel
Imports System.Runtime.CompilerServices
Class MainWindow
Implements INotifyPropertyChanged
Private _TheDictionary As New Dictionary(Of String, Boolean?) From {{"MAYBE", Nothing}, {"YES", True}, {"NO", False}}
Public ReadOnly Property TheDictionary
Get
Return _TheDictionary
End Get
End Property
Private _TheSelection As KeyValuePair(Of String, Boolean?)
Public Property TheSelection As KeyValuePair(Of String, Boolean?)
Get
Return _TheSelection
End Get
Set(value As KeyValuePair(Of String, Boolean?))
SetProperty(_TheSelection, value)
End Set
End Property
Private Sub FindY_Executed(sender As Object, e As ExecutedRoutedEventArgs)
TheSelection = FindY(TheDictionary)
End Sub
Private Function FindY(IDict As IDictionary) As Object
' Let's assume that we don't know TheDictionary generic types.
' We can't iterate through the KeyValuePairs because requires us to know the types at design time
' Find the first dictionary entry with a key that contains Y.
' AsQueryable returns a list of KeyValuePairs
Dim index As Integer = 0
If IDict.Count = 0 Then Return Nothing
For Each o As DictionaryEntry In IDict
If o.Key.ToString.Contains("Y") Then
Return IDict.AsQueryable(index)
End If
index += 1
Next
Return Nothing
End Function
Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged
Public Function SetProperty(Of T)(ByRef storage As T, value As T, <CallerMemberName> Optional PropertyName As String = "") As Boolean
If Object.Equals(storage, value) Then Return False
storage = value
NotifyPropertyChanged(PropertyName)
Return True
End Function
Public Sub NotifyPropertyChanged(PropertyName As String)
RaiseEvent PropertyChanged(Me, New
PropertyChangedEventArgs(PropertyName))
End Sub
End Class
Class MainWindow
Implements INotifyPropertyChanged
Private _TheDictionary As New Dictionary(Of String, Boolean?) From {{"MAYBE", Nothing}, {"YES", True}, {"NO", False}}
Return _TheDictionary
End Property
Private _TheSelection As KeyValuePair(Of String, Boolean?)
Public Property TheSelection As KeyValuePair(Of String, Boolean?)
Return _TheSelection
Set(value As KeyValuePair(Of String, Boolean?))
End Set
End Property
Private Sub FindY_Executed(sender As Object, e As ExecutedRoutedEventArgs)
End Sub
Private Function FindY(IDict As IDictionary) As Object
' Let's assume that we don't know TheDictionary generic types.
' We can't iterate through the KeyValuePairs because requires us to know the types at design time
' Find the first dictionary entry with a key that contains Y.
' AsQueryable returns a list of KeyValuePairs
Dim index As Integer = 0
If IDict.Count = 0 Then Return Nothing
For Each o As DictionaryEntry In IDict
Return IDict.AsQueryable(index)
index += 1
Next
Return Nothing
End Function
Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged
If Object.Equals(storage, value) Then Return False
storage = value
NotifyPropertyChanged(PropertyName)
Return True
End Function
Public Sub NotifyPropertyChanged(PropertyName As String)
End Class