I am creating a wpf application. I have to make all textbox first letter to capital, if a user entered in small then it should be formatted in capital on mouse out.I need the best way to do it, please someone help me.
The best way of doing it greatly depends on how you are doing your app, but #H.B.'s answer is probably the way to go.
For the sake of completeness, another way if doing it would be to use a converter like so:
<!-- Your_Window.xaml -->
<Window x:Class="..."
...
xmlns:cnv="clr-namespace:YourApp.Converters">
<Window.Resources>
<cnv.CapitalizeFirstLetterConverter x:Key="capFirst" />
</Window.Resources>
...
<TextBox Text="{Binding Path=SomeProperty, Converter={StaticResource capFirst}}" />
This assumes that your window's data context is set to an instance of a class that has a read/write property named SomeProperty of type string.
The converter itself would be something like this:
// CapitalizeFirstLetterConverter.cs
using System;
using System.Data;
using System.Globalization;
namespace YourApp.Converters {
[ValueConversion(typeof(string), typeof(string))]
public class CapitalizeFirstLetterConverter : IValueConverter {
public object Convert(object value, Type targetType, object parameter, CultureInfo culture) {
// this will be called after getting the value from your backing property
// and before displaying it in the textbox, so we just pass it as-is
return value;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) {
// this will be called after the textbox loses focus (in this case) and
// before its value is passed to the property setter, so we make our
// change here
if (value is string) {
var castValue = (string)value;
return char.ToUpper(castValue[0]) + castValue.Substring(1);
}
else {
return value;
}
}
}
}
You can learn more about converters here.
You could put a style into the Application.Resources to handle LostFocus on all TextBoxes, then you just need to change the Text property accordingly.
<!-- App.xaml - Application.Resources -->
<Style TargetType="{x:Type TextBox}">
<EventSetter Event="LostFocus" Handler="TextBox_LostFocus" />
</Style>
// App.xaml.cs - App
private void TextBox_LostFocus(object sender, RoutedEventArgs e)
{
var tb = (TextBox)sender;
if (tb.Text.Length > 0)
{
tb.Text = Char.ToUpper(tb.Text[0]) + tb.Text.Substring(1);
}
}
I'm a bit late to the game, but if anybody else needs it this dll capitalizes the first letter in realtime. For example, you don't need to mouse out.
http://www.mardymonkey.co.uk/blog/auto-capitalise-a-text-control-in-wpf/
Perhaps you can use a converter but not a converter like #ssarabando, because it is bugged.
Here's the code of the converter:
using System;
using System.Globalization;
using System.Windows.Data;
namespace SistemaContable.GUI.WPF.Converters
{
public class CapitalizeFirstLetter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value != null)
{
string stringToTitleCase = culture.TextInfo.ToTitleCase(value.ToString());
return stringToTitleCase;
}
else
{
return null;
}
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return value.ToString();
}
}
}
You need to reference it in a "ResourceDictionary" or in your "App.xaml":
<ResourceDictionary xmlns:converters="clr-namespace:SistemaContable.GUI.WPF.Converters">
<converters:CapitalizeFirstLetter x:Key="CapitalizeFirstLetter"/>
</ResourceDictionary>
And you can use it like this:
<TextBox x:Name="txtNombre" Text="{Binding Usuario.Nombre, Converter={StaticResource CapitalizeFirstLetter}, UpdateSourceTrigger=PropertyChanged}"/>
Related
I have a enum to string converter
public class EnumToStringConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter,
CultureInfo culture)
{
MailSettingsStateEnum enumValue = (MailSettingsStateEnum)value;
// extension method on the enum, to return a string based on enum.
return enumValue.Description();
}
// ConvertBack not relevant here.
}
I am using this in wpf xaml easily as follows to set the Content property of a label.
<Label Content="{Binding MailSettingState, Converter={StaticResource
EnumConverterString}}"
BorderBrush="{Binding MailSettingState, Converter={StaticResource
EnumConverterBorderBrush}}" />
Now as you can see, I have another property BorderBrush. I also have to set this based on the same enum. And so I had to write another converter EnumConverterBorderBrush
So is there a way by which I have only one converter, and it return an object which has two properties and i can use these properties in the xaml? I can create the converter, its easy, but I dont know how to use it in xaml. Say the converter returned an object and has tow property called MessageString(of type string), and another BorderBrush of the type Brush, how do I use it the xaml?
You can switch the output based on the targetType you receive in your converter.
So you could do something like this:
public class EnumToStringConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter,
CultureInfo culture)
{
var enumValue = (MailSettingsStateEnum)value;
switch(targetType)
{
case typeof(string)
return enumValue.Description();
case typeof(Brush)
return enumValue.GetBrush();
default:
throw new NotSupportedException("Type not supported")
}
}
// ConvertBack not relevant here.
}
Now you'll have one converter to rule them all!
converter should return object which match requested targetType. converter can return different values for input enum value depending on parameter. I think it is more flexible than relying on targetType only.
public class SpecEnumConverter: IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value is Enum)
{
if ((string) parameter == "brush")
return "Red"; // return brush here!
// if not pre-defined parameter (null or any other), return description
return (int) value; // return enum description here!
}
return value;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
usage:
<Label Content="{Binding MailSettingState, Converter={StaticResource
EnumConverterSpec}}"
BorderBrush="{Binding MailSettingState, Converter={StaticResource
EnumConverterSpec}, ConverterParameter='brush'}" />
I already commented above, but here's the solution.
<Label DataContext="{Binding MailSettingState, Converter={converters:EnumConverter}}" Content="{Binding Label}" BorderBrush="{Binding BorderBrush}"/>
public class EnumConverter: MarkupExtension, IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var enumValue = (MailSettingsStateEnum) value;
return new ConvertedEnum { Label = enumValue.Description(),
BorderBrush = new BorderBrush()};
}
// ConvertBack not relevant here.
public override object ProvideValue(IServiceProvider serviceProvider)
{
return this;
}
}
public class ConvertedEnum
{
public string Label {get; set;}
public BorderBrush {get; set;}
}
Separate converters still look prettier to me.
I have multiple canvas images of different types (image source, geometry, path) and wish to only show 1 depending on a string binding.
whats the best way to do this?
i'd like it to be reusable so i can place this code inside a user control and then have many of these images around the app and i select which 1 is shown.
Like so:
<CanvasImage Image="Pie"/>
<CanvasImage Image="Dog"/>
Would it be too computationally expensive to have them all declared in the user control view and use visibility bindings
Pie canvas example:
<canvas>
<Data ="m24,98,07">
</canvas>
Dog canvas example:
<canvas>
<image source="">
<canvas>
This converter return an image source directly, depending on the value it receives.
namespace TestTreeView.Views
{
public class StringToImageConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
string file = "";
string v = value as string;
switch (v)
{
case "Pie":
file = #".\path\to\your\pie.jpg";
break;
case "Dog":
file = #".\path\to\your\dog.jpg";
break;
default:
return null;
}
return new BitmapImage(new Uri(file, UriKind.RelativeOrAbsolute));
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
}
Usage in XAML:
<Window xmlns:local="clr-namespace:YourNamespace.Views" ...>
<Window.Resources>
<local:StringToImageConverter x:Key="stringToImageConverter"/>
</Window.Resources>
<Grid>
<Canvas>
<Image Source="{Binding YourString, Converter={StaticResource stringToImageConverter}}"/>
</Canvas>
</Grid>
</Window>
Original answer
I think you need to use a Converter.
It will take a ConverterParameter, a String, that will tell what the binded value is expected to be, and return a Visiblity to indicate if the canvas should be visible or not.
namespace YourNamespace.Views
{
public class StringToCanvasVisibilityConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
string v = value as string;
string p = parameter as string;
return (v != null && p != null && v == p) ? Visibility.Visible : Visibility.Collapsed;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
}
Usage in XAML:
<Window xmlns:local="clr-namespace:YourNamespace.Views" ...>
<Window.Resources>
<local:StringToVisibilityConverter x:Key="stringToVisibilityConverter"/>
</Window.Resources>
<Grid>
<Canvas Visibility="{Binding YourString, Converter={StaticResource stringToVisibilityConverter}, ConverterParameter=Pie}"/>
<Canvas Visibility="{Binding YourString, Converter={StaticResource stringToVisibilityConverter}, ConverterParameter=Dog}"/>
</Grid>
</Window>
I'm trying to implement the MVVM design pattern in my WPF application but I have some problems to bind my Views with my ViewModels.
In one of my ViewModels, I have the following property :
public IPEndPoint EndPoint
{
get { return _serverInfos.EndPoint; }
private set
{
_serverInfos.EndPoint = value;
RaisePropertyChanged("EndPoint");
}
}
I want to bind this property in the related View like that :
<TextBox Text="{Binding EndPoint.Address}" />
<TextBox Text="{Binding EndPoint.Port}" />
The EndPoint.Port binding works as expected but the other one doesn't because EndPoint.Address is not a string (it's an IPAddress). Of course, I could define two string properties instead of one IPEndPoint but I think that it's not a good solution.
I also have the same problem using Enums when I want to convert them into int :
<ComboBox SelectedIndex="{Binding MyEnumProperty}" />
How could I solve these problems ?
Thank you for your help.
Normally you want a view model to take things from the model and expose them in a way that the view can consume. As such
MyEnumProperty should be an System.Int32 (int) for ComboBox.SelectedIndex to consumer
You should probably implement two separate properties for EndPointPort and EndPointAddress, and EndPointAddress should be a string that converts to an IPAddress when working with the model
You can use IValueConverters for both of those, but then you are reducing some of the utility of a separate view model in the first place if all it does is act like the model.
A converter you can use for converting between IPAddress and string.
public class IPAddressConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var ipAddress = value as IPAddress;
if (ipAddress != null)
{
return ipAddress.ToString();
}
return DependencyProperty.UnsetValue;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
var text = value as string;
IPAddress ipAddress;
if (text != null && IPAddress.TryParse(text, out ipAddress))
{
return ipAddress;
}
return DependencyProperty.UnsetValue;
}
}
And then in a ResourceDictionary or a Resources collection of a FrameworkElement
<IPAddressConverter x:Key="IpAddressConverter" />
And in the binding:
<TextBox Text="{Binding EndPoint.Address, Converter={StaticResource IpAddressConverter}}" />
As far as the IPEndPoint type, this is a perfect case for a type converter (IValueConverter). It would look something like this, assuming your type has a valid ToString implementation:
public class IPEndPointConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
IPEndPoint endPoint = (IPEndPoint)value;
return endPoint.ToString();
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
You could then add the converter to your XAML file with a ResourceDictionary as follows (assuming you've added the relevant namespace, here called "converters", to your XAML):
<Window.Resources>
<converters:IPEndPointConverter x:Key="ipEndPointConverter" />
</Window.Resources>
You would then simply use this anywhere you need it within your XAML by adding it to the binding:
<TextBox Text="{Binding Path=EndPoint.Address, Converter={StaticResource ResourceKey=ipEndPointConverter}}" />
I have a textblock inside a list view that I need to hide or collapse when it is empty or null. I tried using a string converter but that does not do it.
Any other ideas?
Update # 1:
Here is the code inside the textblock:
Visibility="{Binding Converter={StaticResource StringConverter}}
Here is the converter:
public class StringConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter,
CultureInfo culture)
{
return string.IsNullOrEmpty(value.ToString()) ? Visibility.Collapsed : Visibility.Visible;
}
public object ConvertBack(object value, Type targetType, object parameter,
CultureInfo culture)
{
return DependencyProperty.UnsetValue;
}
}
I would recommend creating text and visibility bindings on your textbox.
Here's an example of the view model properties you'd have.
public String TextBoxText
{
get { return textBoxText; }
set
{
if (value != textBoxText)
{
textBoxText= value;
SetTextBoxVisibility();
OnPropertyChanged("TextBoxText");
}
}
}
private String textBoxText;
public Visibility TextBoxVisibility
{
get { return textBoxVisibility; }
set
{
if (value != textBoxVisibility)
{
textBoxVisibility= value;
OnPropertyChanged("TextBoxVisibility");
}
}
}
private Visibility textBoxVisibility;
public void SetTextBoxVisibility()
{
this.TextBoxVisibility = String.IsNullOrEmpty(this.TextBoxText) ? Visibility.Collapsed : Visibility.Visible;
}
The only thing you've not shown of your code is where you instantiate the converter class. Is this because you're not doing so?
Typically you'd add something like this to app.xaml:
<Application.Resources>
<ResourceDictionary>
<conv:StringConverter x:Key="StringConverter " />
</ResourceDictionary>
</Application.Resources>
Is there a way to automatically capitalize all input throughout a WPF app?
You can case all input into TextBox controls with the following property:
CharacterCasing="Upper"
To apply to all TextBox controls in the entire application create a style for all TextBox controls:
<Style TargetType="{x:Type TextBox}">
<Setter Property="CharacterCasing" Value="Upper"/>
</Style>
If you want to capitalize the input for a single TextBox rather than all TextBoxes like above, you can use the following:
<TextBox CharacterCasing="Upper"/>
I recommend creating a custom Textbox class and override an event to automatically capitalize the text. First, this depends on if you want the text to be capitalize as they type or after input is finished.
E.g. for after input is finished
public class AutoCapizalizeTextBox: TextBox
{
public AutoCapitalizeTextBox()
{
}
public AutoCapitlizeTextBox()
{
}
protected override void OnLostFocus(EventArgs e)
{
this.Text = this.Text.ToUpper();
base.OnLostFocus(e);
}
}
I don't know if this'll help, it capitalizes all the first letters in the sentence.
http://www.mardymonkey.co.uk/blog/auto-capitalise-a-text-control-in-wpf/
Perhaps you can use a converter.
Here's the code of the converter:
using System;
using System.Globalization;
using System.Windows.Data;
namespace SistemaContable.GUI.WPF.Converters
{
public class CapitalizeFirstLetter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value != null)
{
string stringToTitleCase = culture.TextInfo.ToTitleCase(value.ToString());
return stringToTitleCase;
}
else
{
return null;
}
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return value.ToString();
}
}
}
You need to reference it in a "ResourceDictionary" or in your "App.xaml":
<ResourceDictionary xmlns:converters="clr-namespace:SistemaContable.GUI.WPF.Converters">
<converters:CapitalizeFirstLetter x:Key="CapitalizeFirstLetter"/>
</ResourceDictionary>
And you can use it like this:
<TextBox x:Name="txtNombre" Text="{Binding Usuario.Nombre, Converter={StaticResource CapitalizeFirstLetter}, UpdateSourceTrigger=PropertyChanged}"/>