www.planet-xaml.net
 
  • Congratulations, Josh, to your 50th article on the Codeproject... that's quite impressive indeed!

    I do think, however, there is a much simpler solution in this case, which is truely along the WPF way of things without hackery.

    Accessing stuff inside Resource Dictionaries from within a ValueConverter is something I stumbled upon over and over again in XAML. My solution is a combination of MultiBinding and an IMultiConverter. The first Binding resembles the original binding. The second Binding binds to the FrameworkElement that provides the Resource Dictionary scope for the resource.

    In this case, I've added the type of the enum as a ConverterParameter for a generic solution:

    This is how the Binding looks like:

    XAMLtoggle
    <ItemsControl x:Name="_personList">
      
    <ItemsControl.ItemTemplate>
        
    <MultiBinding 
         
    Converter="{StaticResource EnumTypeKeyResourceConverter}" 
         
    ConverterParameter="{x:Type local:DisplayDetailLevel}"
        
    >
          
    <Binding Path="Value" ElementName="_detailLevelSlider" />
          
    <Binding ElementName="_personList" />                        
        
    </MultiBinding>             
      
    </ItemsControl.ItemTemplate>
    </
    ItemsControl>

    The code for the ValueConverter is a little bit more, mostly because of the generic number and enum conversion stuff:

    C#toggle
    public class EnumTypeKeyResourceConverter 
        : IMultiValueConverter
      {
        public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
        {
          if (values.Length < 2) 
                return Binding.DoNothing;

          Object value = values[0];
          var scope = values[1] as FrameworkElement;
          var enumType = parameter as Type;

          if (scope == null || enumType == null)
                return Binding.DoNothing;

          if (!enumType.IsEnum)
                return Binding.DoNothing;
                
          
    // Parse number

          Double d;
          if (!Double.TryParse(System.Convert.ToString(value), out d))
                return Binding.DoNothing;

          
    // to int.. 
          Int32 n = System.Convert.ToInt32(Math.Round(d));

          
    // to enum
          if ((!Enum.IsDefined(enumType, n)))
                return Binding.DoNothing;

          var key = Enum.ToObject(enumType, n);
          Object resource = scope.TryFindResource(key);

          return resource == null ? Binding.DoNothing : resource;
        }

        public object[] ConvertBack(object value, 
                                    Type[] targetTypes, 
                                    object parameter,
                                    CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }

    Cheers,
    Florian


    no comments
  •  ^
  • [XAMLWPF]

    Binding Position Data to an ItemsHost for Layout

    by Florian Krüsch, July 21, 2008

    Edit: Actually Dr.WPF already showed what I was trying to explain here at the end of this post.

    Dr.WPF has added another awesome episode to his continuing ItemsControl saga.

    In the Bonus section he explains how to bind to the ItemContainer from within the ItemTemplate. This reminded me of something... from time to time I ran into the need for exactly the opposite thing: binding to the Item itself from within the ItemContainer.

    The scenario I'm talking about is when the list item contains some kind of position information and you want that to influence the ItemContainer's layout position within the ItemsHost.

    That is, you want a ListBoxItem to show at a position that comes from the object it displays.

    Here's a simple solution:

    Sample data:
    C#toggle
    theListBox.ItemsSource = new[]
    {
        new { Title = 
    "Hello", Pos = new Point(200,30) },
        new { Title = 
    "World", Pos = new Point(100,60) }
    };

    XAML:
    XAMLtoggle
    <ListBox x:Name="theListBox" Width="240" Height="300" Background="Black">
        
        
    <ListBox.ItemTemplate>
            
    <DataTemplate>
                
    <TextBlock Text="{Binding Title}" Background="Pink" />
            
    </DataTemplate>
        
    </ListBox.ItemTemplate>
        
        
    <ListBox.ItemsPanel>
            
    <ItemsPanelTemplate>
                
    <Canvas />
            
    </ItemsPanelTemplate>
        
    </ListBox.ItemsPanel>
        
        
    <ListBox.ItemContainerStyle>
            
    <Style>
                
    <Setter Property="Canvas.Left" Value="{Binding Pos.X}" />
                
    <Setter Property="Canvas.Top" Value="{Binding Pos.Y}" />
            
    </Style>
        
    </ListBox.ItemContainerStyle>
    </
    ListBox>

    Cheers,
    Florian


    no comments
  •  ^
 

Language | Sprache

All[e]  |  english  |  deutsch
Tags
 

Profile

Florian Kruesch

I am working as a freelance software architect, developer and consultant in Düsseldorf, Germany.

My focus is on Microsoft technologies and .NET 3.0, especially WPF, ASP.net and SQL Server.

I've been a lead programmer on the WPF development of the OTTO Vista Store at SinnerSchrader Studios.

My client list includes DHL, LG and Ogilvy Interactive.