tags:

views:

34

answers:

1

i would like to make the LineBreak element inside of that TextBlock controllable by the user in preferences to Enable/Disable it being there

<TextBlock Style="{StaticResource TextBlockStyle}" Width="130">
<TextBlock.Inlines>
    <Run Text="{Binding Path=Name}" FontWeight="Bold" Foreground="#FF2A4D9E" />
    <Run Text="{Binding Path=Price}" FontWeight="Bold" />

       <LineBreak  />

    <Run Text="{Binding Path=Quantity}" Foreground="#99000000" />
</TextBlock.Inlines>
</TextBlock>
+1  A: 

I don't believe there is any way in a FlowDocument to make a LineBreak not really break except to take it out. Your choices are to switch to using WPF layout or to use an attached property to switch between a LineBreak and an empty Run.

Using WPF layout

You may consider using WPF layout instead. Something like this:

<DataTemplate x:Key="Layout1">
  <DockPanel>
    <TextBlock Text="{Binding Name}" FontWeight="Bold" Foreground="#FF2A4D9E" />
    <TextBlock Text="{Binding Price}" FontWeight="Bold" />
    <TextBlock Text="{Binding Quantity}" Foreground="#99000000" />
  </DockPanel>
</DataTemplate>

<DataTemplate x:Key="Layout2">
  <DockPanel>
    <DockPanel DockPanel.Dock="Top">
      <TextBlock Text="{Binding Name}" FontWeight="Bold" Foreground="#FF2A4D9E" />
      <TextBlock Text="{Binding Price}" FontWeight="Bold" />
    </DockPanel>

    <TextBlock Text="{Binding Quantity}" Foreground="#99000000" />
  </DockPanel>
</DataTemplate>

Now you can easily switch between layouts just by switching DataTemplates.

Automatically removing LineBreaks using bindings

If you want to "hide" the LineBreak via a binding you can do it with an attached "BecomeLineBreak" property that, when applied to an empty Run and set true, removes it and replaces it with a LineBreak.

Like magic you now have the ability to write:

<Run my:LineBreakSwitcher.BecomeLineBreak="{Binding SomeCondition}" />

And your Run will turn into a LineBreak any time the SomeCondition property is true.

Here is the code:

public class LineBreakSwitcher : DependencyObject
{
  public static bool GetBecomeLineBreak(DependencyObject obj) { return (bool)obj.GetValue(BecomeLineBreakProperty); }
  public static void SetBecomeLineBreak(DependencyObject obj, bool value) { obj.SetValue(BecomeLineBreakProperty, value); }
  public static readonly DependencyProperty BecomeLineBreakProperty = DependencyProperty.RegisterAttached("BecomeLineBreak", typeof(bool), typeof(LineBreakSwitcher), new PropertyMetadata
  {
    PropertyChangedCallback = (obj, e) =>
      {
        var oldElement = (Inline)obj;
        var newElement = (bool)e.NewValue ? (Inline)new LineBreak() : new Run();
        newElement.SetBinding(BecomeLineBreakProperty, oldElement.GetBindingExpression(BecomeLineBreakProperty).ParentBindingBase);

        var parent = (Paragraph)oldElement.Parent;
        parent.Inlines.InsertBefore(oldElement, newElement);
        parent.Inlines.Remove(oldElement);
      }
  });

How it works: When BecomeLineBreak becomes true on a Run, a new LineBreak is created, the BecomeLineBreak binding is copied across, the LineBreak is inserted before the Run, then the Run is removed. When BecomeLineBreak become false, a new Run is created and the whole process happens in reverse.

Ray Burns
yes.. accept my textblock is templated and big, so i was hoping to avoid this approach not to edit in multiple places. thansk though
Sonic Soul
Then I guess you do need the code solution. I have updated my answer to give the algorithm you will need. It is not very much code really - perhaps 50 lines - but I don't have time to type it up right now.
Ray Burns
wild. thanks :)
Sonic Soul
You're welcome. I just realized this can be done with a single "BecomeLineBreak" attached property. I updated my answer with this simplification including the actual code to do it. It turned out to be 16 lines instead of 50.
Ray Burns