Add brackets to text box value - c#

I want to know if there is option that when I type into a text box or drag to anything (I'm using D&D functionality), the text on it will automatically insert brackets. I don't want to do that on the logic or in the code beyond just in the ui. Is that posible?
For example: if I type AAA, I will see in the text box (AAA).

I dont want to do that on the logic or in the code beyond
By your conditions it is not possible. Something has to capture the change event and add the brackets to the text. That something is not possible without logic as found in code behind.
The options are
Subscribe to the textblock's SelectionChange event and add the brackets.
Create a custom control which does #1 internal so the consumer doesn't have to do it. (By a technicality it answer's your question).
Put the textblock control between two labels which have the brackets as their context. Bind their visibility to a Boolean on the VM which reports when the bound data of the textblock has changed. If there is text then they become visible, if there is no text it is hidden. Downside is that this is not caught as the user types or until it fully changed, only when exiting the control.
Here is #3
<Label Content="(" Visibility="{Binding HasText, Converter={StaticResource WindowsVisibilityBooleanConverter}}" />
<TextBox Text="{Binding TextInput}"
Height="18"
HorizontalAlignment="Stretch" />
<Label Content=")" Visibility="{Binding HasText, Converter={StaticResource WindowsVisibilityBooleanConverter}}" />

Without any of your own logic code, I suppose this is the closest thing to what you want.
<TextBox x:Name="tbInput" />
<TextBlock Text="{Binding ElementName='tbInput', Path=Text, StringFormat={}({0})}" />
The downside would be that you'll always see the empty brackets () if the TextBox is empty.

See: String format using MultiBinding?
<StackPanel>
<Slider x:Name="sl1" Minimum="10" Maximum="100"/>
<Slider x:Name="sl2" Minimum="10" Maximum="100"/>
<Label x:Name="label13" Background="Yellow" Foreground="Black">
<Label.Content>
<TextBlock>
<TextBlock.Text>
<MultiBinding StringFormat="{}{0} x {1} Test">
<Binding ElementName="sl1" Path="Value" />
<Binding ElementName="sl2" Path="Value" />
</MultiBinding>
</TextBlock.Text>
</TextBlock>
</Label.Content>
</Label>
</StackPanel>

Related

WPF C# - TextBlock inside custom ProgressBar not showing [duplicate]

This may be a no-brainer for the WPF cognoscenti, but I'd like to know if there's a simple way to put text on the WPF ProgressBar. To me, an empty progress bar looks naked. That's screen real estate that could carry a message about what is in progress, or even just add numbers to the representation. Now, WPF is all about containers and extensions and I'm slowly wrapping my mind around that, but since I don't see a "Text" or "Content" property, I'm thinking I'm going to have to add something to the container that is my progress bar. Is there a technique or two out there that is more natural than my original WinForms impulses will be? What's the best, most WPF-natural way to add text to that progress bar?
Both of the prior responses (creating a new CustomControl or an Adorner) are better practices, but if you just want quick and dirty (or to understand visually how to do it) then this code would work:
<Grid Width="300" Height="50">
<ProgressBar Value="50" />
<TextBlock HorizontalAlignment="Center" VerticalAlignment="Center">
My Text
</TextBlock>
</Grid>
Just keep in mind that the z-index is such that the last item listed will be on top.
Also, if you don't have Kaxaml yet, be sure to pick it up - it is great for playing with XAML when you're trying to figure things out.
This can be very simple (unless there are alot of ways getting this to work).
You could use Style to get this done or you just overlay a TextBlock and a ProgressBar.
I personally use this to show the percentage of the progress when waiting for completion.
To keep it very simple I only wanted to have one Binding only,
so I attached the TextBock.Text to the ProgressBar.Value.
Then just copy the Code to get it done.
<Grid>
<ProgressBar Minimum="0"
Maximum="100"
Value="{Binding InsertBindingHere}"
Name="pbStatus" />
<TextBlock Text="{Binding ElementName=pbStatus, Path=Value, StringFormat={}{0:0}%}"
HorizontalAlignment="Center"
VerticalAlignment="Center" />
</Grid>
Here is how this could look like:
Check out WPF Tutorial for the full post.
If you are needing to have a reusable method for adding text, you can create a new Style/ControlTemplate that has an additional TextBlock to display the text. You can hijack the TextSearch.Text attached property to set the text on a progress bar.
If it doesn't need to be reusable, simply put the progress bar in a Grid and add a TextBlock to the grid. Since WPF can compose elements together, this will work nicely.
If you want, you can create a UserControl that exposes the ProgressBar and TextBlock as public properties, so it would be less work than creating a custom ControlTemplate.
You could use an Adorner to display text over top of it.
See MSDN article on Adorners
You would create a class that inherits from the Adorner class. Override the OnRender method to draw the text that you want. If you want you could create a dependency property for your custom Adorner that contains the text that you want to display. Then use the example in the link I mentioned to add this Adorner to your progress bar's adorner layer.
ProgressBar with Text and Binding from 2 Properties ( Value/Maximum value ):
<Grid>
<ProgressBar Name="pbUsrLvl"
Minimum="1"
Maximum="99"
Value="59"
Margin="5"
Height="24" Foreground="#FF62FF7F"/>
<TextBlock HorizontalAlignment="Center" VerticalAlignment="Center">
<TextBlock.Text>
<MultiBinding StringFormat="{}UserLvl:{0}/{1}">
<Binding Path="Value" ElementName="pbUsrLvl" />
<Binding Path="Maximum" ElementName="pbUsrLvl" />
</MultiBinding>
</TextBlock.Text>
</TextBlock>
</Grid>
Rezult:
The same but with % of progress :
<Grid>
<ProgressBar Name="pbLifePassed"
Minimum="0"
Value="59"
Maximum="100"
Margin="5" Height="24" Foreground="#FF62FF7F"/>
<TextBlock Text="{Binding ElementName=pbLifePassed, Path=Value, StringFormat={}{0:0}%}"
HorizontalAlignment="Center" VerticalAlignment="Center" />
</Grid>
Right click ProgressBar, and click Edit Template > Edit a Copy.
Then put the TextBlock as shown below just above the closing tag of Grid in the Style generated by VS.
<Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="2"/>
<TextBlock Background="Transparent" Text="work in progress" Foreground="Black" TextAlignment="Center"/>
</Grid>
<ControlTemplate.Triggers>
This is based on the given answers.
Since I´m using MahApps Metro, I ended up with this:
<Grid>
<metro:MetroProgressBar x:Name="pbar" Value="50" Height="20"></metro:MetroProgressBar>
<TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" Text="{Binding ElementName=pbar, Path=Value, StringFormat={}{0:0}%}"></TextBlock>
</Grid>
If you want to use the normal bar with Metro Style:
<Grid>
<ProgressBar x:Name="pbar" Value="50" Height="20" Style="{StaticResource MetroProgressBar}"></ProgressBar>
<TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" Text="{Binding ElementName=pbar, Path=Value, StringFormat={}{0:0}%}"></TextBlock>
</Grid>
Same without Style:
<Grid>
<ProgressBar x:Name="pbar" Value="60" Height="20" Style="{x:Null}"></ProgressBar>
<TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" Text="{Binding ElementName=pbar, Path=Value, StringFormat={}{0:0}%}"></TextBlock>
</Grid>
What is Happening?
You have your progressbar and simply just lay text over it.
So you just use your progressbar as you would.
Put the progressbar in a grid and lay an textblock in it.
Then you can text as you wish or grab the current percenteage wich is the value from the progressbar.

How to make WPF label side by side?

I am trying to put 2 label in stackpanel (Which is in grid) side by side but it's not wokring. the 2nd label come to the 2nd line.
I tried 2 textblock in content property but it doesn't work. I try settting Orientation and ContentAlignment mention in stackoverflow doesn't make any changes.
The first label is bold and another one is normal. Anyone have any idea how to make it work.
Here is the code.
<Label Style="{StaticResource FormHead}">
<Label.Content>
<TextBlock>aaa</TextBlock>
<TextBlock>bbb</TextBlock>
</Label.Content>
</Label>
You can simply do it as below :
<StackPanel Orientation="Horizontal">
<TextBlock>aaa</TextBlock>
<TextBlock>bbb</TextBlock>
</StackPanel>
Try this.
<Label>
<Label.Content>
<StackPanel Orientation="Horizontal">
<TextBlock>aaa</TextBlock>
<TextBlock>bbb</TextBlock>
</StackPanel>
</Label.Content>
</Label>

Force RadioButtons to only change if the bound value actually changes

I have a bit of a strange case. The issue is that I have 3 radiobuttons and they are binded to the EffectiveValue property of my viewmodel.
<StackPanel Grid.Column="2" Orientation="Horizontal" Margin="5,0,0,0">
<StackPanel.Visibility>
<MultiBinding Converter="{StaticResource MultiBoolToVisibilityHidden}">
<Binding Path="IsSelected" RelativeSource="{RelativeSource AncestorType=telerik:RadListBoxItem}"/>
<Binding Path="Criterion.IsOverridable"/>
<Binding Path="DataContext.CanOverrideEvaluation" ElementName="ThisInformationControl"/>
</MultiBinding>
</StackPanel.Visibility>
<telerik:RadRadioButton Content="Y" IsChecked="{Binding EffectiveValue, Converter={StaticResource EnumToBool}, ConverterParameter={x:Static utilities:Ternary.TRUE}, Mode=OneWay}" Style="{StaticResource EmptyRadioButtonStyle}"
Command="{Binding OverrideValueCommand}" CommandParameter="{x:Static utilities:Ternary.TRUE}" Margin="2,1" Width="16" VerticalAlignment="Center"/>
<telerik:RadRadioButton Content="?" IsChecked="{Binding EffectiveValue, Converter={StaticResource EnumToBool}, ConverterParameter={x:Static utilities:Ternary.UNKNOWN}, Mode=OneWay}" Style="{StaticResource EmptyRadioButtonStyle}"
Command="{Binding OverrideValueCommand}" CommandParameter="{x:Static utilities:Ternary.UNKNOWN}" Margin="2,1" Width="16" VerticalAlignment="Center"/>
<telerik:RadRadioButton Content="N" IsChecked="{Binding EffectiveValue, Converter={StaticResource EnumToBool}, ConverterParameter={x:Static utilities:Ternary.FALSE}, Mode=OneWay}" Style="{StaticResource EmptyRadioButtonStyle}"
Command="{Binding OverrideValueCommand}" CommandParameter="{x:Static utilities:Ternary.FALSE}" Margin="2,1" Width="16" VerticalAlignment="Center"/>
</StackPanel>
The problem is this. Say my ViewModel Effective Value is 'Y'. I click the 'N' button. But then based on certain conditions, I do not actually set the EffectiveValue to 'N' and it remains 'Y'. The problem I am having is now the 'N' looks selected even though the viewmodel still says that the value is 'Y'. What can I do to make sure my radiobuttons strictly listen to the viewmodel's value?
My current workaround it to force a property changed on the effective value but I feel this is kind of a hack.
Thanks
I think the answer lies with your radio button bindings. Notice that you have them set to OneWay, but you said that based on certain conditions you keep the value as 'Y'. How does the WPF control know that you've rejected the UI change?
I suggest changing the binding Mode to TwoWay and maybe also include UpdateSourceTrigger=PropertyChanged in the bindings. Then your code behind and the UI can communicate "two ways" to each other about what the appropriate state of the radio button should be.

WPF Keep visible elements and sample texts in them after binding at DesignTime

I have two element on my window:
A TextBlock
A Button
I can see the Button in design-time by this code
<Button x:Name="BtnHelp" Content="HELP"/>
But i can't see the Botton in design-time after binding:
<Button x:Name="BtnHelp" Content="HELP" Visibility="{Binding Visibility_BtnHelp , Converter={StaticResource BoolToVisConverter}}" />
Also i can see sample text in my TextBlock
<TextBlock Text="Sample Text" />
But can't have a sample data in my TextBlock in design-time after binding:
<TextBlock Text="{Binding Field}" />
How can i have fake data and statuses in my elements just in design-time with a easy way after binding??
Do you suggest a way base on d:... property in XAML or another way?
This:
<Button x:Name="BtnHelp" Content="HELP" Visibility="{Binding Visibility_BtnHelp , Converter={StaticResource BoolToVisConverter}, FallbackValue=Visible}" />
<TextBlock Text="{Binding Field, FallbackValue='Sample Text'}" />
Setting a FallbackValue will also prevent binding errors in the event of a null DataContext so it is good practice.

Hyperlink - content binding

I have a TextBox where a user inputs a uri. This then becomes the NavigateUri property of a hyperlink, allowing the user to click on the link to open the page.
<!-- Input TextBox -->
<TextBox x:Name="linkBox" Width="175" Text="{Binding Path=DocRef, Mode=TwoWay}" />
<!-- Hyperlink -->
<TextBlock>
<Hyperlink DataContext="{Binding ElementName=linkBox}" NavigateUri="{Binding
Path=Text}" RequestNavigate="Hyperlink_RequestNavigate">
<TextBlock DataContext="{Binding ElementName=linkBox}"
Text="{Binding Path=Text}" />
</Hyperlink>
</TextBlock>
This works for inputting the whole (absolute) uri in the TextBox. However, the user wants to only input the 'document.extn' bit of the Uri, and have the application prepend the rest of the resource (ie, the 'http://www.example.com/' bit). How do I set the base part of the uri and append the document reference (preferably in xaml)? I came across Hyperlink's BaseUri property which sounds perfect, but unfortunately is protected, so this doesn't work:
<Hyperlink DataContext="{Binding ElementName=linkBox}"
BaseUri="http://www.example.com/" NavigateUri="{Binding Path=Text}"
RequestNavigate="Hyperlink_RequestNavigate">
Can anybody assist?
You may be able to use MultiBinding to join the 2 strings you need
<Hyperlink DataContext="{Binding ElementName=linkBox}" RequestNavigate="Hyperlink_RequestNavigate">
<Hyperlink.NavigateUri>
<MultiBinding StringFormat="{}{0}{1}">
<Binding FallbackValue="http://www.example.com/" />
<Binding Path="Text" />
</MultiBinding>
</Hyperlink.NavigateUri>
</Hyperlink>
You can create a Custom Converter using IValueConverter interface to get the base uri appended uri.

Categories