<?xml version="1.0" encoding="utf-8"?>
<rss xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:pingback="http://madskills.com/public/xml/rss/module/pingback/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:georss="http://www.georss.org/georss" xmlns:dc="http://purl.org/dc/elements/1.1/" version="2.0">
  <channel>
    <title>DotNetDude.com - WPF</title>
    <link>http://www.dotnetdude.com/</link>
    <description>Miguel A. Castro's Blog</description>
    <image>
      <url>http://www.dotnetdude.com/feed-icon-24x24.gif</url>
      <title>DotNetDude.com - WPF</title>
      <link>http://www.dotnetdude.com/</link>
    </image>
    <language>en-us</language>
    <copyright>Miguel A. Castro</copyright>
    <lastBuildDate>Sun, 23 Jan 2011 20:24:02 GMT</lastBuildDate>
    <generator>newtelligence dasBlog 2.3.9074.18820</generator>
    <managingEditor>miguelcastro67@gmail.com</managingEditor>
    <webMaster>miguelcastro67@gmail.com</webMaster>
    <item>
      <trackback:ping>http://www.dotnetdude.com/Trackback.aspx?guid=982904ee-baaa-42b4-a5e8-496be9c98009</trackback:ping>
      <pingback:server>http://www.dotnetdude.com/pingback.aspx</pingback:server>
      <pingback:target>http://www.dotnetdude.com/PermaLink,guid,982904ee-baaa-42b4-a5e8-496be9c98009.aspx</pingback:target>
      <dc:creator>Miguel A. Castro</dc:creator>
      <wfw:comment>http://www.dotnetdude.com/CommentView,guid,982904ee-baaa-42b4-a5e8-496be9c98009.aspx</wfw:comment>
      <wfw:commentRss>http://www.dotnetdude.com/SyndicationService.asmx/GetEntryCommentsRss?guid=982904ee-baaa-42b4-a5e8-496be9c98009</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
I’ve been beating my head against the wall with a small problem and after lots of
trial and error, and some searching around, I found the answer – and it was NOT obvious
!
</p>
        <p>
The problem space was simple and common:
</p>
        <p>
I have placed a lot of my styles, data templates, and converters into separate XAML
files (ResourceDictionaries), with the idea of just declaring them in the App.Xaml
since I’m pretty much using these all over the application.  I started out declaring
things in my App.Xaml like this:
</p>
        <p>
 
</p>
        <pre class="brush: xml;">&lt;Application.Resources&gt;
    &lt;controls:BooleanToVisibilityConverter x:Key="booleanToVisibilityConverter" /&gt;
    &lt;refractionConverter:ReverseBooleanToVisibilityConverter x:Key="reverseBooleanToVisibilityConverter" /&gt;
    &lt;refractionConverter:PercentageConverter x:Key="percentageConverter" /&gt;
    &lt;ResourceDictionary&gt;
        &lt;ResourceDictionary.MergedDictionaries&gt;
            &lt;ResourceDictionary&gt;
            &lt;/ResourceDictionary&gt;
            &lt;ResourceDictionary Source="Resources/SharedResources.xaml" /&gt;
            &lt;ResourceDictionary Source="Resources/MdiTemplates.xaml" /&gt;
        &lt;/ResourceDictionary.MergedDictionaries&gt;
    &lt;/ResourceDictionary&gt;
&lt;/Application.Resources&gt;

</pre>
        <p>
 
</p>
        <p>
Looks simple enough right?  Wrong.
</p>
        <p>
The second I moved the converters from the individual User Controls to the <strong>App.Xaml</strong>,
styles that are declared in the <strong>SharedResources.xaml</strong> file became
unreachable.  In my debugging efforts, I tapped into the <strong>Application_Startup</strong> event
to examine the resources that WPF was loading.  I noticed that the value of <strong>this.Resources.Count</strong> was <strong>4</strong>,
but the value of <strong>this.Resources.MergedDictionaries.Count</strong> was <strong>0</strong>.  
</p>
        <p>
So I continued digging and here’s what I found out:
</p>
        <p>
Once you commit to using <strong>MergedDictionaries</strong> in your <strong>App.Xaml</strong>,
you must use them for everything.  I moved the three converters inside the <strong>MergedDictionaries</strong> section
and tested the debugging again.  This time, <strong>this.Resources.Count</strong> was
set to <strong>0</strong>, and <strong>this.Resources.MergedDictionaries.Count</strong> was
set to <strong>3</strong>.  This told me the resources I listed as <strong>MergedDictionaries</strong> were
now loading.  The key indicator that things were better is that my styles now
worked.
</p>
        <p>
Here’s the code:
</p>
        <p>
 
</p>
        <pre class="brush: xml;">&lt;Application.Resources&gt;
    &lt;ResourceDictionary&gt;
        &lt;ResourceDictionary.MergedDictionaries&gt;
            &lt;ResourceDictionary&gt;
                &lt;controls:BooleanToVisibilityConverter x:Key="booleanToVisibilityConverter" /&gt;
                &lt;refractionConverter:ReverseBooleanToVisibilityConverter x:Key="reverseBooleanToVisibilityConverter" /&gt;
                &lt;refractionConverter:PercentageConverter x:Key="percentageConverter" /&gt;
            &lt;/ResourceDictionary&gt;
            &lt;ResourceDictionary Source="Resources/SharedResources.xaml" /&gt;
            &lt;ResourceDictionary Source="Resources/MdiTemplates.xaml" /&gt;
        &lt;/ResourceDictionary.MergedDictionaries&gt;
    &lt;/ResourceDictionary&gt;
&lt;/Application.Resources&gt;

</pre>
        <p>
 
</p>
        <p>
I hope this helps since believe it or not, though there’s a lot of code samples out
there, much of it is unclear and flat out wrong.
</p>
        <h3>
          <em>Until next time…</em>
        </h3>
        <img width="0" height="0" src="http://www.dotnetdude.com/aggbug.ashx?id=982904ee-baaa-42b4-a5e8-496be9c98009" />
      </body>
      <title>Resource Dictionaries Are Making My Hair Hurt!</title>
      <guid isPermaLink="false">http://www.dotnetdude.com/PermaLink,guid,982904ee-baaa-42b4-a5e8-496be9c98009.aspx</guid>
      <link>http://www.dotnetdude.com/2011/01/23/ResourceDictionariesAreMakingMyHairHurt.aspx</link>
      <pubDate>Sun, 23 Jan 2011 20:24:02 GMT</pubDate>
      <description>&lt;p&gt;
I’ve been beating my head against the wall with a small problem and after lots of
trial and error, and some searching around, I found the answer – and it was NOT obvious
!
&lt;/p&gt;
&lt;p&gt;
The problem space was simple and common:
&lt;/p&gt;
&lt;p&gt;
I have placed a lot of my styles, data templates, and converters into separate XAML
files (ResourceDictionaries), with the idea of just declaring them in the App.Xaml
since I’m pretty much using these all over the application.&amp;nbsp; I started out declaring
things in my App.Xaml like this:
&lt;/p&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;pre class="brush: xml;"&gt;&amp;lt;Application.Resources&amp;gt;
    &amp;lt;controls:BooleanToVisibilityConverter x:Key="booleanToVisibilityConverter" /&amp;gt;
    &amp;lt;refractionConverter:ReverseBooleanToVisibilityConverter x:Key="reverseBooleanToVisibilityConverter" /&amp;gt;
    &amp;lt;refractionConverter:PercentageConverter x:Key="percentageConverter" /&amp;gt;
    &amp;lt;ResourceDictionary&amp;gt;
        &amp;lt;ResourceDictionary.MergedDictionaries&amp;gt;
            &amp;lt;ResourceDictionary&amp;gt;
            &amp;lt;/ResourceDictionary&amp;gt;
            &amp;lt;ResourceDictionary Source="Resources/SharedResources.xaml" /&amp;gt;
            &amp;lt;ResourceDictionary Source="Resources/MdiTemplates.xaml" /&amp;gt;
        &amp;lt;/ResourceDictionary.MergedDictionaries&amp;gt;
    &amp;lt;/ResourceDictionary&amp;gt;
&amp;lt;/Application.Resources&amp;gt;

&lt;/pre&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p&gt;
Looks simple enough right?&amp;nbsp; Wrong.
&lt;/p&gt;
&lt;p&gt;
The second I moved the converters from the individual User Controls to the &lt;strong&gt;App.Xaml&lt;/strong&gt;,
styles that are declared in the &lt;strong&gt;SharedResources.xaml&lt;/strong&gt; file became
unreachable.&amp;nbsp; In my debugging efforts, I tapped into the &lt;strong&gt;Application_Startup&lt;/strong&gt; event
to examine the resources that WPF was loading.&amp;nbsp; I noticed that the value of &lt;strong&gt;this.Resources.Count&lt;/strong&gt; was &lt;strong&gt;4&lt;/strong&gt;,
but the value of &lt;strong&gt;this.Resources.MergedDictionaries.Count&lt;/strong&gt; was &lt;strong&gt;0&lt;/strong&gt;.&amp;nbsp; 
&lt;/p&gt;
&lt;p&gt;
So I continued digging and here’s what I found out:
&lt;/p&gt;
&lt;p&gt;
Once you commit to using &lt;strong&gt;MergedDictionaries&lt;/strong&gt; in your &lt;strong&gt;App.Xaml&lt;/strong&gt;,
you must use them for everything.&amp;nbsp; I moved the three converters inside the &lt;strong&gt;MergedDictionaries&lt;/strong&gt; section
and tested the debugging again.&amp;nbsp; This time, &lt;strong&gt;this.Resources.Count&lt;/strong&gt; was
set to &lt;strong&gt;0&lt;/strong&gt;, and &lt;strong&gt;this.Resources.MergedDictionaries.Count&lt;/strong&gt; was
set to &lt;strong&gt;3&lt;/strong&gt;.&amp;nbsp; This told me the resources I listed as &lt;strong&gt;MergedDictionaries&lt;/strong&gt; were
now loading.&amp;nbsp; The key indicator that things were better is that my styles now
worked.
&lt;/p&gt;
&lt;p&gt;
Here’s the code:
&lt;/p&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;pre class="brush: xml;"&gt;&amp;lt;Application.Resources&amp;gt;
    &amp;lt;ResourceDictionary&amp;gt;
        &amp;lt;ResourceDictionary.MergedDictionaries&amp;gt;
            &amp;lt;ResourceDictionary&amp;gt;
                &amp;lt;controls:BooleanToVisibilityConverter x:Key="booleanToVisibilityConverter" /&amp;gt;
                &amp;lt;refractionConverter:ReverseBooleanToVisibilityConverter x:Key="reverseBooleanToVisibilityConverter" /&amp;gt;
                &amp;lt;refractionConverter:PercentageConverter x:Key="percentageConverter" /&amp;gt;
            &amp;lt;/ResourceDictionary&amp;gt;
            &amp;lt;ResourceDictionary Source="Resources/SharedResources.xaml" /&amp;gt;
            &amp;lt;ResourceDictionary Source="Resources/MdiTemplates.xaml" /&amp;gt;
        &amp;lt;/ResourceDictionary.MergedDictionaries&amp;gt;
    &amp;lt;/ResourceDictionary&amp;gt;
&amp;lt;/Application.Resources&amp;gt;

&lt;/pre&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p&gt;
I hope this helps since believe it or not, though there’s a lot of code samples out
there, much of it is unclear and flat out wrong.
&lt;/p&gt;
&lt;h3&gt;&lt;em&gt;Until next time…&lt;/em&gt;
&lt;/h3&gt;
&lt;img width="0" height="0" src="http://www.dotnetdude.com/aggbug.ashx?id=982904ee-baaa-42b4-a5e8-496be9c98009" /&gt;</description>
      <comments>http://www.dotnetdude.com/CommentView,guid,982904ee-baaa-42b4-a5e8-496be9c98009.aspx</comments>
      <category>Dev Stuff</category>
      <category>WPF</category>
    </item>
    <item>
      <trackback:ping>http://www.dotnetdude.com/Trackback.aspx?guid=ae5a82d3-5df7-4aec-be18-77b8bed522d8</trackback:ping>
      <pingback:server>http://www.dotnetdude.com/pingback.aspx</pingback:server>
      <pingback:target>http://www.dotnetdude.com/PermaLink,guid,ae5a82d3-5df7-4aec-be18-77b8bed522d8.aspx</pingback:target>
      <dc:creator>Miguel A. Castro</dc:creator>
      <wfw:comment>http://www.dotnetdude.com/CommentView,guid,ae5a82d3-5df7-4aec-be18-77b8bed522d8.aspx</wfw:comment>
      <wfw:commentRss>http://www.dotnetdude.com/SyndicationService.asmx/GetEntryCommentsRss?guid=ae5a82d3-5df7-4aec-be18-77b8bed522d8</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
One of my latest challenges involved the topic of WPF sizing.  I’m referring
to the manipulation of control widths in relation to their parent widths.  Most
books tell you that this happens automatically, but I’m here to say otherwise gentle
reader.  Now, I am fully prepared to admit that I may have missed something so
if you’re a WPF expert out there and you think there is a better way to do what I’m
going to show you, please respond.  
</p>
        <p>
So here is my situation:
</p>
        <p>
I have a window (user control actually, but then almost everything is in most WPF
applications).  My window defines a grid with two columns, each which will contain
a user control of their own.  It looked something like this:
</p>
        <p>
 
</p>
        <pre class="brush: xml; ruler: false;">&lt;Grid&gt;
    &lt;Grid.ColumnDefinitions&gt;
        &lt;ColumnDefinition Width="300" /&gt;
        &lt;ColumnDefinition Width="*" /&gt;
    &lt;/Grid.ColumnDefinitions&gt;
    &lt;src:Control1 Grid.Column="0" x:Name="ctlControl1" DataContext="{Binding Path=Control1ViewModel}" /&gt;
    &lt;src:Control2 Grid.Column="2" x:Name="ctlControl2" /&gt;
&lt;/Grid&gt;
</pre>
        <p>
The user control called <strong>Control1</strong> contains a <a href="http://msdn.microsoft.com/en-us/library/system.windows.controls.listview.aspx" target="_blank">ListView</a> control
which defined an <strong>ItemTemplate</strong> to construct the content structure
of each item.  The effect I wanted was to show the data for each item in read-only
mode and provide an “edit” icon on each item.  Pressing it would convert that
item to editable textboxes.  I got that working fine by providing two Grids inside
my data template, setting one of them invisible, then using commanding on the button
icons to change the view-model state to switch the <a href="http://msdn.microsoft.com/en-us/library/system.windows.visibility.aspx" target="_blank">Visibility</a> of
each grid was bound – worked like a charm and is a really nice effect.
</p>
        <p>
My problem was that both the <a href="http://msdn.microsoft.com/en-us/library/system.windows.controls.textblock.aspx" target="_blank">TextBlock</a> and <a href="http://msdn.microsoft.com/en-us/library/system.windows.controls.textbox.aspx" target="_blank">TextBox</a> controls
in each item view sized to its contents, then the widest one became the width of the
actual <strong>ListView</strong> that contained everything.  Originally, the
column that contained this entire user control (defined above) was set to <strong>Auto</strong>,
so of course it would widen to the width of the longest text control.  This totally
sucked.
</p>
        <p>
I added a splitter to the grid in the user control that contained the other two controls
and the results at first were weird.  I took the recommendation of most books
and added the <a href="http://msdn.microsoft.com/en-us/library/system.windows.controls.gridsplitter.aspx" target="_blank">GridSplitter</a> to
its own column (set to Auto width) at first.  This enabled me to resize the grid
columns but by then, the content user control’s width was already set and it would
not resize along with my resize-drag.  Dragging the splitter to the right, left
the contents of the first column fixed, and dragging to the left basically didn’t
work past the already fixed-width of the first column.  I fixed this by adding
the <strong>GridSplitter</strong> as the last control on the same column as one of
the controls, like this:
</p>
        <p>
 
</p>
        <pre class="brush: xml; ruler: false;">&lt;Grid&gt;
    &lt;Grid.ColumnDefinitions&gt;
        &lt;ColumnDefinition Width="300" /&gt;
        &lt;ColumnDefinition Width="*" /&gt;
    &lt;/Grid.ColumnDefinitions&gt;
    &lt;src:Control1Grid.Column="0" x:Name="ctlControl1" DataContext="{Binding Path=Control1ViewModel}" /&gt;
    &lt;GridSplitter ResizeDirection="Columns" Grid.Column="0" Width="3" /&gt;
    &lt;src:Control2 Grid.Column="2" x:Name="ctlControl2" /&gt;
&lt;/Grid&gt;
</pre>
        <p>
 
</p>
        <p>
Now when I drag the splitter, the columns follow along the resize in both directions;
however the <strong>TextBlock</strong> and <strong>TextBox</strong> controls in my <strong>ListView</strong> remain
sized to their contents and would not stretch in either direction.  This still
totally sucked.
</p>
        <p>
After playing around significantly with this, I discovered that the <strong>ListView</strong> itself
was sizing and resizing dynamically as I dragged my splitter so I needed to get the
contents of each item to size similarly.  The solution was to bind the <strong>Width</strong> of
each of my <strong>TextBlock</strong> and <strong>TextBox</strong> items to the width
of the <strong>ListView</strong> in which they were contained.  I gave the <strong>ListView</strong> control
a name (I don’t normally name my controls since most of my work happens in the View-Model
anyway), then set the <strong>Width</strong> property of the contained controls like
this:
</p>
        <p>
 
</p>
        <pre class="brush: xml; ruler: false;">&lt;ListView Name="lvw1" ItemsSource="{Binding}" DataContext="{Binding Path=VuewModelPropertyGoesHere}"&gt;
    &lt;ListView.ItemTemplate&gt;
        &lt;DataTemplate&gt;
            &lt;Grid&gt;
                &lt;Grid Visibility="{Binding Path=EditMode, Converter={StaticResource notEditModeVisibilityConverter}, Mode=OneWay}"&gt;
                    &lt;Grid.RowDefinitions&gt;
                        &lt;RowDefinition Height="25" /&gt;
                        &lt;RowDefinition Height="Auto" /&gt;
                        &lt;RowDefinition Height="25" /&gt;
                        &lt;RowDefinition Height="10" /&gt;
                    &lt;/Grid.RowDefinitions&gt;
                    &lt;Grid.ColumnDefinitions&gt;
                        &lt;ColumnDefinition Width="*" /&gt;
                    &lt;/Grid.ColumnDefinitions&gt;
                    &lt;TextBlock Grid.Row="0" Grid.Column="0" Text="{Binding Path=Name}" TextWrapping="Wrap" HorizontalAlignment="Stretch"<br />
Width="{Binding ElementName=lvw1, Path=ActualWidth}" Margin="0,0,5,0" /&gt; &lt;TextBlock
Grid.Row="1" Grid.Column="0" Text="{Binding Path=Description}" TextWrapping="Wrap"
HorizontalAlignment="Stretch" 
<br />
Width="{Binding ElementName=lvw1, Path=ActualWidth}" Margin="0,0,5,0" /&gt; . . .
&lt;/Grid&gt; &lt;Grid Visibility="{Binding Path=EditMode, Converter={StaticResource
editModeVisibilityConverter}, Mode=OneWay}"&gt; &lt;Grid.RowDefinitions&gt; &lt;RowDefinition
Height="25" /&gt; &lt;RowDefinition Height="Auto" /&gt; &lt;RowDefinition Height="*"
/&gt; &lt;RowDefinition Height="10" /&gt; &lt;/Grid.RowDefinitions&gt; &lt;Grid.ColumnDefinitions&gt;
&lt;ColumnDefinition Width="*" /&gt; &lt;/Grid.ColumnDefinitions&gt; &lt;TextBox Grid.Row="0"
Grid.Column="0" Text="{Binding Path=Name, UpdateSourceTrigger=PropertyChanged}" 
<br />
Width="{Binding ElementName=lvw1, Path=ActualWidth, Mode=OneWay}" Margin="0,0,5,0"
VerticalAlignment="Center" /&gt; &lt;TextBox Grid.Row="1" Grid.Column="0" Text="{Binding
Path=Description, UpdateSourceTrigger=PropertyChanged}" 
<br />
TextWrapping="Wrap" AcceptsReturn="True" MaxLines="3" MinLines="3" VerticalScrollBarVisibility="Auto"<br />
Width="{Binding ElementName=lvw1, Path=ActualWidth, Mode=OneWay}" Margin="0,0,5,0"
VerticalAlignment="Center" /&gt; </pre>
        <p>
 
</p>
        <p>
This totally fixed my problem… almost.  While the binding worked perfectly, the
look I got left one little detail to be desired.  You see, now the width of the
textboxes as equal to the width of the <strong>ListView</strong>.  This made
their right edge disappear, and no margin and padding setting would fix it.
</p>
        <p>
What I needed to do is set the width of the controls to slightly less than the width
of the <strong>ListView</strong>; 10 pixels less to be exact.  Apparently in
WPF, you either bind or you do not bind; not a combination of the two.  And you
certainly cannot do mathematics in the XAML.  So what to do?
</p>
        <p>
At this point, I had become quite comfortable with the idea of a type-converter so
this is the first thing that sprung into my mind.  I created a type converter
that I could use in this binding.  The job of the type converter would be to
take the incoming width, and rather than convert it to another type, simply adjust
by a certain amount and return that number.  And what amount you ask?  Well,
the type converter gives you a “parameter’ argument than you can fill in the XAML,
so the answer is: any amount I desire.
</p>
        <p>
The end-result worked and looked great.  Here’s the type converter code:
</p>
        <p>
 
</p>
        <pre class="brush: csharp; ruler: false;">public class WidthToParentConverter : IValueConverter
{
    object IValueConverter.Convert(object value, Type targetType, object parameter,
        System.Globalization.CultureInfo culture)
    {
        double width = (double)value;
        double adjustment = Convert.ToDouble(parameter);

        return width + adjustment;
    }

    object IValueConverter.ConvertBack(object value, Type targetType, object parameter,
        System.Globalization.CultureInfo culture)
    {
        double width = (double)value;
        double adjustment = Convert.ToDouble(parameter);

        return width - adjustment;
    }
}
</pre>
        <p>
 
</p>
        <p>
And here’s the adjusted XAML for the textboxes:
</p>
        <p>
 
</p>
        <pre class="brush: xml; ruler: false;">&lt;TextBox Grid.Row="0" Grid.Column="0" Text="{Binding Path=Name, UpdateSourceTrigger=PropertyChanged}"<br />
Width="{Binding ElementName=lvw1, Path=ActualWidth, Converter={StaticResource widthToParentConverter},
ConverterParameter=-10, Mode=OneWay}"<br />
Margin="0,0,5,0" VerticalAlignment="Center" /&gt; &lt;TextBox Grid.Row="1" Grid.Column="0"
Text="{Binding Path=Description, UpdateSourceTrigger=PropertyChanged}"<br />
TextWrapping="Wrap" AcceptsReturn="True" MaxLines="3" MinLines="3" VerticalScrollBarVisibility="Auto" 
<br />
Width="{Binding ElementName=lvw1, Path=ActualWidth, Converter={StaticResource widthToParentConverter},
ConverterParameter=-10, Mode=OneWay}" 
<br />
Margin="0,0,5,0" VerticalAlignment="Center" /&gt; </pre>
        <p>
 
</p>
        <p>
 
</p>
        <p>
I struggled with this for a quite a bit, mainly because of inexperience, but now I
know exactly what to do in this situation and I hope sharing it helps some of you
as well.
</p>
        <p>
 
</p>
        <h3>
          <em>Until Next Time…</em>
        </h3>
        <img width="0" height="0" src="http://www.dotnetdude.com/aggbug.ashx?id=ae5a82d3-5df7-4aec-be18-77b8bed522d8" />
      </body>
      <title>Binding Widths In WPF With A Slight Adjustment</title>
      <guid isPermaLink="false">http://www.dotnetdude.com/PermaLink,guid,ae5a82d3-5df7-4aec-be18-77b8bed522d8.aspx</guid>
      <link>http://www.dotnetdude.com/2010/09/24/BindingWidthsInWPFWithASlightAdjustment.aspx</link>
      <pubDate>Fri, 24 Sep 2010 20:38:46 GMT</pubDate>
      <description>&lt;p&gt;
One of my latest challenges involved the topic of WPF sizing.&amp;nbsp; I’m referring
to the manipulation of control widths in relation to their parent widths.&amp;nbsp; Most
books tell you that this happens automatically, but I’m here to say otherwise gentle
reader.&amp;nbsp; Now, I am fully prepared to admit that I may have missed something so
if you’re a WPF expert out there and you think there is a better way to do what I’m
going to show you, please respond.&amp;nbsp; 
&lt;/p&gt;
&lt;p&gt;
So here is my situation:
&lt;/p&gt;
&lt;p&gt;
I have a window (user control actually, but then almost everything is in most WPF
applications).&amp;nbsp; My window defines a grid with two columns, each which will contain
a user control of their own.&amp;nbsp; It looked something like this:
&lt;/p&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;pre class="brush: xml; ruler: false;"&gt;&amp;lt;Grid&amp;gt;
    &amp;lt;Grid.ColumnDefinitions&amp;gt;
        &amp;lt;ColumnDefinition Width="300" /&amp;gt;
        &amp;lt;ColumnDefinition Width="*" /&amp;gt;
    &amp;lt;/Grid.ColumnDefinitions&amp;gt;
    &amp;lt;src:Control1 Grid.Column="0" x:Name="ctlControl1" DataContext="{Binding Path=Control1ViewModel}" /&amp;gt;
    &amp;lt;src:Control2 Grid.Column="2" x:Name="ctlControl2" /&amp;gt;
&amp;lt;/Grid&amp;gt;
&lt;/pre&gt;
&lt;p&gt;
The user control called &lt;strong&gt;Control1&lt;/strong&gt; contains a &lt;a href="http://msdn.microsoft.com/en-us/library/system.windows.controls.listview.aspx" target="_blank"&gt;ListView&lt;/a&gt; control
which defined an &lt;strong&gt;ItemTemplate&lt;/strong&gt; to construct the content structure
of each item.&amp;nbsp; The effect I wanted was to show the data for each item in read-only
mode and provide an “edit” icon on each item.&amp;nbsp; Pressing it would convert that
item to editable textboxes.&amp;nbsp; I got that working fine by providing two Grids inside
my data template, setting one of them invisible, then using commanding on the button
icons to change the view-model state to switch the &lt;a href="http://msdn.microsoft.com/en-us/library/system.windows.visibility.aspx" target="_blank"&gt;Visibility&lt;/a&gt; of
each grid was bound – worked like a charm and is a really nice effect.
&lt;/p&gt;
&lt;p&gt;
My problem was that both the &lt;a href="http://msdn.microsoft.com/en-us/library/system.windows.controls.textblock.aspx" target="_blank"&gt;TextBlock&lt;/a&gt; and &lt;a href="http://msdn.microsoft.com/en-us/library/system.windows.controls.textbox.aspx" target="_blank"&gt;TextBox&lt;/a&gt; controls
in each item view sized to its contents, then the widest one became the width of the
actual &lt;strong&gt;ListView&lt;/strong&gt; that contained everything.&amp;nbsp; Originally, the
column that contained this entire user control (defined above) was set to &lt;strong&gt;Auto&lt;/strong&gt;,
so of course it would widen to the width of the longest text control.&amp;nbsp; This totally
sucked.
&lt;/p&gt;
&lt;p&gt;
I added a splitter to the grid in the user control that contained the other two controls
and the results at first were weird.&amp;nbsp; I took the recommendation of most books
and added the &lt;a href="http://msdn.microsoft.com/en-us/library/system.windows.controls.gridsplitter.aspx" target="_blank"&gt;GridSplitter&lt;/a&gt; to
its own column (set to Auto width) at first.&amp;nbsp; This enabled me to resize the grid
columns but by then, the content user control’s width was already set and it would
not resize along with my resize-drag.&amp;nbsp; Dragging the splitter to the right, left
the contents of the first column fixed, and dragging to the left basically didn’t
work past the already fixed-width of the first column.&amp;nbsp; I fixed this by adding
the &lt;strong&gt;GridSplitter&lt;/strong&gt; as the last control on the same column as one of
the controls, like this:
&lt;/p&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;pre class="brush: xml; ruler: false;"&gt;&amp;lt;Grid&amp;gt;
    &amp;lt;Grid.ColumnDefinitions&amp;gt;
        &amp;lt;ColumnDefinition Width="300" /&amp;gt;
        &amp;lt;ColumnDefinition Width="*" /&amp;gt;
    &amp;lt;/Grid.ColumnDefinitions&amp;gt;
    &amp;lt;src:Control1Grid.Column="0" x:Name="ctlControl1" DataContext="{Binding Path=Control1ViewModel}" /&amp;gt;
    &amp;lt;GridSplitter ResizeDirection="Columns" Grid.Column="0" Width="3" /&amp;gt;
    &amp;lt;src:Control2 Grid.Column="2" x:Name="ctlControl2" /&amp;gt;
&amp;lt;/Grid&amp;gt;
&lt;/pre&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p&gt;
Now when I drag the splitter, the columns follow along the resize in both directions;
however the &lt;strong&gt;TextBlock&lt;/strong&gt; and &lt;strong&gt;TextBox&lt;/strong&gt; controls in my &lt;strong&gt;ListView&lt;/strong&gt; remain
sized to their contents and would not stretch in either direction.&amp;nbsp; This still
totally sucked.
&lt;/p&gt;
&lt;p&gt;
After playing around significantly with this, I discovered that the &lt;strong&gt;ListView&lt;/strong&gt; itself
was sizing and resizing dynamically as I dragged my splitter so I needed to get the
contents of each item to size similarly.&amp;nbsp; The solution was to bind the &lt;strong&gt;Width&lt;/strong&gt; of
each of my &lt;strong&gt;TextBlock&lt;/strong&gt; and &lt;strong&gt;TextBox&lt;/strong&gt; items to the width
of the &lt;strong&gt;ListView&lt;/strong&gt; in which they were contained.&amp;nbsp; I gave the &lt;strong&gt;ListView&lt;/strong&gt; control
a name (I don’t normally name my controls since most of my work happens in the View-Model
anyway), then set the &lt;strong&gt;Width&lt;/strong&gt; property of the contained controls like
this:
&lt;/p&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;pre class="brush: xml; ruler: false;"&gt;&amp;lt;ListView Name="lvw1" ItemsSource="{Binding}" DataContext="{Binding Path=VuewModelPropertyGoesHere}"&amp;gt;
    &amp;lt;ListView.ItemTemplate&amp;gt;
        &amp;lt;DataTemplate&amp;gt;
            &amp;lt;Grid&amp;gt;
                &amp;lt;Grid Visibility="{Binding Path=EditMode, Converter={StaticResource notEditModeVisibilityConverter}, Mode=OneWay}"&amp;gt;
                    &amp;lt;Grid.RowDefinitions&amp;gt;
                        &amp;lt;RowDefinition Height="25" /&amp;gt;
                        &amp;lt;RowDefinition Height="Auto" /&amp;gt;
                        &amp;lt;RowDefinition Height="25" /&amp;gt;
                        &amp;lt;RowDefinition Height="10" /&amp;gt;
                    &amp;lt;/Grid.RowDefinitions&amp;gt;
                    &amp;lt;Grid.ColumnDefinitions&amp;gt;
                        &amp;lt;ColumnDefinition Width="*" /&amp;gt;
                    &amp;lt;/Grid.ColumnDefinitions&amp;gt;
                    &amp;lt;TextBlock Grid.Row="0" Grid.Column="0" Text="{Binding Path=Name}" TextWrapping="Wrap" HorizontalAlignment="Stretch"&lt;br&gt;
Width="{Binding ElementName=lvw1, Path=ActualWidth}" Margin="0,0,5,0" /&amp;gt; &amp;lt;TextBlock
Grid.Row="1" Grid.Column="0" Text="{Binding Path=Description}" TextWrapping="Wrap"
HorizontalAlignment="Stretch" 
&lt;br&gt;
Width="{Binding ElementName=lvw1, Path=ActualWidth}" Margin="0,0,5,0" /&amp;gt; . . .
&amp;lt;/Grid&amp;gt; &amp;lt;Grid Visibility="{Binding Path=EditMode, Converter={StaticResource
editModeVisibilityConverter}, Mode=OneWay}"&amp;gt; &amp;lt;Grid.RowDefinitions&amp;gt; &amp;lt;RowDefinition
Height="25" /&amp;gt; &amp;lt;RowDefinition Height="Auto" /&amp;gt; &amp;lt;RowDefinition Height="*"
/&amp;gt; &amp;lt;RowDefinition Height="10" /&amp;gt; &amp;lt;/Grid.RowDefinitions&amp;gt; &amp;lt;Grid.ColumnDefinitions&amp;gt;
&amp;lt;ColumnDefinition Width="*" /&amp;gt; &amp;lt;/Grid.ColumnDefinitions&amp;gt; &amp;lt;TextBox Grid.Row="0"
Grid.Column="0" Text="{Binding Path=Name, UpdateSourceTrigger=PropertyChanged}" 
&lt;br&gt;
Width="{Binding ElementName=lvw1, Path=ActualWidth, Mode=OneWay}" Margin="0,0,5,0"
VerticalAlignment="Center" /&amp;gt; &amp;lt;TextBox Grid.Row="1" Grid.Column="0" Text="{Binding
Path=Description, UpdateSourceTrigger=PropertyChanged}" 
&lt;br&gt;
TextWrapping="Wrap" AcceptsReturn="True" MaxLines="3" MinLines="3" VerticalScrollBarVisibility="Auto"&lt;br&gt;
Width="{Binding ElementName=lvw1, Path=ActualWidth, Mode=OneWay}" Margin="0,0,5,0"
VerticalAlignment="Center" /&amp;gt; &lt;/pre&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p&gt;
This totally fixed my problem… almost.&amp;nbsp; While the binding worked perfectly, the
look I got left one little detail to be desired.&amp;nbsp; You see, now the width of the
textboxes as equal to the width of the &lt;strong&gt;ListView&lt;/strong&gt;.&amp;nbsp; This made
their right edge disappear, and no margin and padding setting would fix it.
&lt;/p&gt;
&lt;p&gt;
What I needed to do is set the width of the controls to slightly less than the width
of the &lt;strong&gt;ListView&lt;/strong&gt;; 10 pixels less to be exact.&amp;nbsp; Apparently in
WPF, you either bind or you do not bind; not a combination of the two.&amp;nbsp; And you
certainly cannot do mathematics in the XAML.&amp;nbsp; So what to do?
&lt;/p&gt;
&lt;p&gt;
At this point, I had become quite comfortable with the idea of a type-converter so
this is the first thing that sprung into my mind.&amp;nbsp; I created a type converter
that I could use in this binding.&amp;nbsp; The job of the type converter would be to
take the incoming width, and rather than convert it to another type, simply adjust
by a certain amount and return that number.&amp;nbsp; And what amount you ask?&amp;nbsp; Well,
the type converter gives you a “parameter’ argument than you can fill in the XAML,
so the answer is: any amount I desire.
&lt;/p&gt;
&lt;p&gt;
The end-result worked and looked great.&amp;nbsp; Here’s the type converter code:
&lt;/p&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;pre class="brush: csharp; ruler: false;"&gt;public class WidthToParentConverter : IValueConverter
{
    object IValueConverter.Convert(object value, Type targetType, object parameter,
        System.Globalization.CultureInfo culture)
    {
        double width = (double)value;
        double adjustment = Convert.ToDouble(parameter);

        return width + adjustment;
    }

    object IValueConverter.ConvertBack(object value, Type targetType, object parameter,
        System.Globalization.CultureInfo culture)
    {
        double width = (double)value;
        double adjustment = Convert.ToDouble(parameter);

        return width - adjustment;
    }
}
&lt;/pre&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p&gt;
And here’s the adjusted XAML for the textboxes:
&lt;/p&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;pre class="brush: xml; ruler: false;"&gt;&amp;lt;TextBox Grid.Row="0" Grid.Column="0" Text="{Binding Path=Name, UpdateSourceTrigger=PropertyChanged}"&lt;br&gt;
Width="{Binding ElementName=lvw1, Path=ActualWidth, Converter={StaticResource widthToParentConverter},
ConverterParameter=-10, Mode=OneWay}"&lt;br&gt;
Margin="0,0,5,0" VerticalAlignment="Center" /&amp;gt; &amp;lt;TextBox Grid.Row="1" Grid.Column="0"
Text="{Binding Path=Description, UpdateSourceTrigger=PropertyChanged}"&lt;br&gt;
TextWrapping="Wrap" AcceptsReturn="True" MaxLines="3" MinLines="3" VerticalScrollBarVisibility="Auto" 
&lt;br&gt;
Width="{Binding ElementName=lvw1, Path=ActualWidth, Converter={StaticResource widthToParentConverter},
ConverterParameter=-10, Mode=OneWay}" 
&lt;br&gt;
Margin="0,0,5,0" VerticalAlignment="Center" /&amp;gt; &lt;/pre&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p&gt;
I struggled with this for a quite a bit, mainly because of inexperience, but now I
know exactly what to do in this situation and I hope sharing it helps some of you
as well.
&lt;/p&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;h3&gt;&lt;em&gt;Until Next Time…&lt;/em&gt;
&lt;/h3&gt;
&lt;img width="0" height="0" src="http://www.dotnetdude.com/aggbug.ashx?id=ae5a82d3-5df7-4aec-be18-77b8bed522d8" /&gt;</description>
      <comments>http://www.dotnetdude.com/CommentView,guid,ae5a82d3-5df7-4aec-be18-77b8bed522d8.aspx</comments>
      <category>Dev Stuff</category>
      <category>WPF</category>
    </item>
  </channel>
</rss>