give a textblock a margin but only if there is content - silverlight

I have 3 textblocks in a stackpanel in a DataTemplate.
the idea is that the format should be like "a b c" with spaces between the textblocks but it may happen that textblocks "a" and "b" might be empty, so i end up with something like this " c" ( two spaces before textblock c). How can i ensure that i have a margin but only if there is content?

If the TextBlock's Visibility is set to Collapsed, the Margin will not be shown. So I guess you can use a StringToVisibilityConverter to set its Visibility to Collapsed if the Text is empty.
Example
First you need to create a converter like this.
public class StringToVisibilityConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (value == null)
return Visibility.Collapsed;
if (value != null && string.IsNullOrWhiteSpace(value.ToString()))
return Visibility.Collapsed;
return Visibility.Visible;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
Then you need to include this converter into your xaml.
<converters:StringToVisibilityConverter x:Key="StringToVisibilityConverter " />
Finally, use it inside your TextBlock.
<TextBlock x:Name="MyTextBlock" Text="{Binding SomeText}"
Visibility="{Binding SomeText, Converter={StaticResource StringToVisibilityConverter}}" />
For more info regarding how to use a converter, please take a look at this post.
Hope it helps. :)

Add a converter to the Margin and bind it to the Text property. Have the converter sent the margin to a uniform thickness of 0 if the text content is blank.

Put the textblocks in a grid so that their locations are fixed. Add a converter to the martin and bind it to the text property, and if the length of that text is zero, then set the margin to zero.

Related

ListView Columns Header - after last header there is a white gap

It's hard to explain with words.
I did a style and template for ListView similar to this: https://learn.microsoft.com/en-us/dotnet/framework/wpf/controls/listview-styles-and-templates
I turned out like this:
As you can see, in the header, there is a weird white gap after the last column. How can I fix this?
Normally you can set the width in WPF like width = "*" and it would automatically fill the empty gap. However, as far as I know, it is not possible to do in ListView. You can either have a fixed width or have it on auto. If I were you I would switch to DataGrid.
If you really want to stick to ListView I would suggest to have a custom IValueConverter. You can Bind the Width of GridViewColumn to the ActualWidth of the ListView.
public class StarWidthConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
ListView listview = value as ListView;
double width = listview.Width;
GridView gv = listview.View as GridView;
for (int i = 0; i < gv.Columns.Count; i++)
{
if (!Double.IsNaN(gv.Columns[i].Width))
width -= gv.Columns[i].Width;
}
return width -5;// this is to take care of margin/padding
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return null;
}
}
maybe your ListView is inside a Grid so default value for HorizontalAlignment will be Stretch , ListView will auto generate a blank column to fill all availible space,to avoid that you can put your ListView inside a StackPanel then set Orientation to "Horizontal" or explicity set HorizontalAlignment value for ListView .Something like this
<ListBox HorizontalAlignment="Left"/>

How do I bind a DataGrid Width to a converter?

I want to include the size of the VerticalScrollbar when i define the width of a DataGrid.
So far i wrote a Converter:
[ValueConversion(typeof(double), typeof(double))]
public class VerticalScrollbarConverter : IValueConverter
{
#region IValueConverter Member
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (value is double)
return (double)value + SystemParameters.VerticalScrollBarWidth;
else
return value;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
#endregion
}
I included my converter in the xaml namespace with:
xmlns:Core="clr-namespace:Core;assembly=SMS_Core"
And I defined the converter as a (window) resource:
<Window.Resources>
<Core:VerticalScrollbarConverter x:Key="VerticalScrollbarConverter"/>
</Window.Resources>
Since all of my DataGrid.Columns have a fixed Value I know the value that i need to pass.
How do I tell my GridView Width property in xaml to use the converter?
I know that my question is pretty basic. As you can tell I am very new to WPF.
Thanks in advance for every hint. If you need some more info or context just ask away.
The comment from sa_ddam213 didn't exactly solve the problem. But it sure did push me into the right direction.
To pass the value automatically I had to do the following:
I created a property in the window class called TotalColumnWidth. Returning this:
myDataGrid.Columns.Sum(c => c.ActualWidth);
The xaml is the following:
Width="{Binding ElementName=_Root, Path=TotalColumnWidth, Converter={StaticResource ResourceKey=VerticalScrollbarConverter}}"
Using the converter mentioned above.

How to get the value of an inherited FontSize property in an UserControl?

I am working on Windows Phone 7.1 application.
I have a UserControl which has a bunch Silverlight child controls. The font sizes for most of these child controls can be same as that of the host of the said UserControl (which will anyway get inherited from the host).
However for one of the child controls, I want to set the FontSize to half the FontSize of the UserControl. And I want it to update if the FontSize of the host changes.
But now during the UserControl design time, since there is no host, I am unable make this work. Doing something like 0.5*FontSize results in some default value of FontSize and it does not get updated when the FontSize changes.
What should I be doing to make it work?
You can bind your FontSize property to the FontSize property of your UserControl and use a converter to do the ratio.
Here's a sample with a textblock inside a page:
<TextBlock FontSize="{Binding ElementName=MyPage, Path=FontSize,
Converter={StaticResource FontSizeConverter}}"
Text="any text" />
And the converter (declared as a resource in the App.xaml file:
public class FontSizeConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var valueToConvert = value == null ? 0 : System.Convert.ToDouble(value);
return valueToConvert * 0.5;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException("no use");
}
}

WPF bind IsEnabled on other controls if a listbox has a select item

I have a grid with 2 columns, a listbox in column 0 and a number of other controls in the a secondary grid in the main grids column 1.
I want this controls only to be enabled (or perhaps visible) if an items is selected in the listbox through binding. I tried on a combo box:
IsEnabled="{Binding myList.SelectedIndex}"
But that does not seem to work.
Am I missing something? Should something like this work?
thanks
You'll need a ValueConverter for this. This article describes it in detail, but the summary is you need a public class that implements IValueConverter. In the Convert() method, you could do something like this:
if(!(value is int)) return false;
if(value == -1) return false;
return true;
Now, in your XAML, you need to do:
<Window.Resources>
<local:YourValueConverter x:Key="MyValueConverter">
</Window.Resources>
And finally, modify your binding to:
IsEnabled="{Binding myList.SelectedIndex, Converter={StaticResource MyValueConverter}"
Are you sure you didn't mean
IsEnabled="{Binding ElementName=myList, Path=SelectedIndex, Converter={StaticResource MyValueConverter}"
though? You can't implicitly put the element's name in the path (unless the Window itself is the DataContext, I guess). It might also be easier to bind to SelectedItem and check for not null, but that's really just preference.
Oh, and if you're not familiar with alternate xmlns declarations, up at the top of your Window, add
xmlns:local=
and VS will prompt you for the various possibilities. You need to find the one that matches the namespace you put the valueconverter you made in.
Copy-paste solution:
Add this class to your code:
public class HasSelectedItemConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return value is int && ((int) value != -1);
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
Add converter as StaticResource to App.xml in <Application.Resources> section:
<local:HasSelectedItemConverter x:Key="HasSelectedItemConverter" />
And now you can use it in your XAML:
<Button IsEnabled="{Binding ElementName=listView1, Path=SelectedIndex,
Converter={StaticResource HasSelectedItemConverter}"/>
Hmm, perhaps it works with a BindingConverter, which converts explicitly all indexes > 0 to true.

How to display the text in one line in wpf textblock

I'm a newbie with wpf , what i want to display the text in one line in wpf textblock.
eg.:
<TextBlock
Text ="asfasfasfa
asdasdasd"
</TextBlock>
TextBlock display it in two lines default,
but i want it in only one line like this"asafsf asfafaf". I mean show all the text in one line even there are more than one lines in the text
what should i do?
Use a Converter:
<TextBlock Text={Binding Path=TextPropertyName,
Converter={StaticResource SingleLineTextConverter}}
SingleLineTextConverter.cs:
public class SingleLineTextConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
string s = (string)value;
s = s.Replace(Environment.NewLine, " ");
return s;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
Instead of this:
<TextBlock Text="Hello
How Are
You??"/>
Use this:
<TextBlock>
Hello
How Are
You??
</TextBlock>
or this:
<TextBlock>
<Run>Hello</Run>
<Run>How Are</Run>
<Run>You??</Run>
</TextBlock>
or set Text property in code behind like this :
(In XAML)
<TextBlock x:Name="MyTextBlock"/>
(In code - c#)
MyTextBlock.Text = "Hello How Are You??"
Code-behind approach has an advantage that you can format your text before setting it.
Example: If the text is retrieved from a file and you want to remove any carriage-return new-line characters you can do it this way:
string textFromFile = System.IO.File.ReadAllText(#"Path\To\Text\File.txt");
MyTextBlock.Text = textFromFile.Replace("\n","").Replace("\r","");

Resources