views:

176

answers:

1

I have a ListBox showing data about employees such as name, department photo, badge number, etc. Employees may have different types such as Manager, Staff, Volunteers. I have 3 separate data templates - one for each type. All of these templates show basically the same data but presented differently.

Depending on the user logged into the application pictures, Badge Number, etc, can or cannot be visible. So I have boolean properties for that - CanSeePhotos, CanSeeBadgeNumbers, etc. So if CanSeePhotos == false, all data templates should hide the photos.

My question is, how can I use these boolean properties inside my data templates to toggle the visibility of the appropriate items? Is there a way to pass parameters to Data Templates as I return them from my TemplateSelector?

Thanks!

edit: following Ray's idea I ended up doing this:

Visibility="{Binding Source={x:Static local:Global.CanSeePhoto}, Converter={StaticResource BooleanToVisibilityConverter}}"
A: 

Actually there is a way to customize DataTemplates as they are returned from the TemplateSelector by wrapping them inside a FrameworkElementFactory, but it is much too complex for your needs.

For your case there are two solutions that are much easier: triggers and converters.

Triggers

You can use a trigger inside the DataTemplate. For example, give the TextBox or Panel where you display the badge number an x:Name, then create a DataTrigger on the CanSeeBadgeNumebers property. Add one setter to the DataTrigger and set the Visible property to Hidden or Collapsed, referencing it by name.

Basic idea:

<DataTemplate>
  ...
  <DockPanel x:Name="BadgeNumberPanel">
    <Label ... />
    <TextBox ... />
  </DockPanel>
  ...

  <DataTemplate.Triggers>
    <DataTrigger Binding="{Binding CanSeeBadgeNumbers}" Value="true">
      <Setter ElementName="BadgeNumberPanel" Property="Visibility" Value="Collapsed" />
    </DataTrigger>
  </DataTemplate.Triggers>
</DataTemplate>

Converters

You can create an IValueConverter in code that converts "bool" type to "Visibility" type (there are many examples out there you can cut and paste), then bind the visibilty of the TextBox to the CanSeeBadgeNumbers, using the converter.

<DockPanel Visibility="{Binding CanSeeBadgeNumbers, Converter="{x:Static local:BoolToVisibilityConverter.Instance}}">
  <Label ... />
  <TextBox ... />
</DockPanel>

How I Do It

I actually use a different technique for my own code: My data foundation includes a MarkupExtension I wrote that calls my core C# expression parser, so I can say something like

Visibility="{edf:Visibility CanSeeBadgeNumber || Owner.SecurityLevel.Count() > 3}"

Unfortunately my data foundation has not yet been released. When it is, I plan to make it free and open source, but that's a few months away yet.

Ray Burns
If your CanSeeBadgeNumber is not a property of the data but of the environment you might have to add something like Source="{x:Static UserInfo.CurrentUser}" to your binding. This is the same whether you use triggers or converters.
Ray Burns
Expressions in XAML bindings! I've been waiting for that for a long time - really miss it from my Flex days. Looking forward to seeing it!
Groky