Sunday, June 21, 2015

XAML Celsius Fahrenheit converter (no code behind)

Ever wanted to convert Celsius to Fahrenheit in your WPF application, without any code behind?

Here is how you do it, using a trick I learnt from Charles Petzold.

<DockPanel>

 <FrameworkElement Name="calcC2F" Visibility="Collapsed">
   <FrameworkElement.RenderTransform>
     <TransformGroup>
       <TranslateTransform X="{Binding ElementName=sldr, Path=Value}" />
         <ScaleTransform ScaleX="1.8" />
          <TranslateTransform X="32" />
         </TransformGroup>
        </FrameworkElement.RenderTransform>
       </FrameworkElement>
        
  <Slider Name="sldr" Minimum="-100" Maximum="100" TickFrequency="1"            IsSnapToTickEnabled="True" Value="0" Margin="5" DockPanel.Dock="Top"/>
        
  <DockPanel>

    <TextBlock Text="{Binding ElementName=sldr,Path=Value, StringFormat={}{0}°C}" FontSize="36" DockPanel.Dock="Top" HorizontalAlignment="Center"/>
      
    <TextBlock Text="{Binding ElementName=calcC2F, Path=RenderTransform.Value.OffsetX, StringFormat={}{0}°F}" 
FontSize="36" HorizontalAlignment="Center"/>
        
  </DockPanel>

 </DockPanel>




You can apply this principle to many occasions when you need to calculate something in XAML without having to resort to code behind!

Wednesday, April 2, 2014

ToggleButton with Popup

Need a ToogleButton with a Popup that behaves nicely?

Have you done this (see XAML below) and wondered why the popup closes and reopens when you click the ToggleButton again and again, the ToggleButton is always checked until you click outside the button or the popup.

<Grid>
    <ToggleButton Name="tbWithPopup" Width="30" Height="30"
               IsChecked="{Binding ElementName=pUp, Path=IsOpen}">
        <Polygon Points="0,0 2,0, 1,1" Fill="Black" Stretch="Fill" />
    </ToggleButton>
        
    <Popup Name="pUp"
           PlacementTarget="{Binding ElementName=tbWithPopup}"
           AllowsTransparency="True" StaysOpen="False" Width="200">
        <RichTextBox IsReadOnly="True">
            <RichTextBox.Document>
                <FlowDocument>
                    <Paragraph>
                       Checkout WPF Tat for more elegant 
                       solutions
                    </Paragraph>
                </FlowDocument>
            </RichTextBox.Document>
        </RichTextBox>
    </Popup>
</Grid>

What is happening, is that when you click the ToggleButton the second time, the Popup closes, resets the ToggleButton's IsChecked state to False and your click causes the ToggleButton's IsChecked state to change to True again, and thus the Popup closes and reopens.

How do we solve this? 

Turns out there is a very elegant solution to this problem. By setting the IsHitTestVisble property of the ToggleButton to False when the Popup is open. 

We can easy do this in XAML by adding a style to the ToggleButton. Like this ...

<ToggleButton.Style>
    <Style TargetType="ToggleButton">
        <Style.Triggers>
            <DataTrigger Binding="{Binding ElementName=pUp, Path=IsOpen}" 
                         Value="True">
                <Setter Property="IsHitTestVisible" Value="False" />
            </DataTrigger>
         </Style.Triggers>
    </Style>
</ToggleButton.Style>

Now, everything behaves as you would expect, and no code behind required :)