TextBox Placeholder text while also Binding to ListBox.SelectedItem - c#

How can I still have a Placeholder text (.Text = "Whatever") while also binding the textbox to a ListBox's Selected Item?

When do you want this placeholder text to display? When there is no SelectedItem?
You could use PriorityBinding which will allow you to provide a list of bindings and it will use the first that produces a result.
Something like:
<TextBox>
<TextBox.Text>
<PriorityBinding>
<Binding Path="myListBox.SelectedItem"/>
<Binding Source="Default Text"/>
</PriorityBinding>
</TextBox.text>
</TextBox>

Related

WPF influencing the order of databinding?

I have created an AttachedProperty that has a PropertyChangedCallback function, which does some formatting to a TextBlock. But to perform the formatting, the Tag attribute is needed. The Tag itself is bound to the output of a Multiconverter.
But my problem is, that the FNamePropertChangedCallback is executed before the Tag is bound to the output of the Multibinding. Thus Tag still Null, when FNamePropertyChangedCallback is triggered.
Is there any way to influence the order in which the Attributes are bound?
I need to bind Tag before binding FInlineProperty.
public static readonly DependencyProperty FInlinePropertyProperty =
DependencyProperty.RegisterAttached("FInlineProperty", typeof(string), typeof(MainWindow),
new PropertyMetadata(null, FNamePropertyChangedCallback));
<TextBlock local:MainWindow.FInlineProperty="{Binding Name}" TextWrapping="WrapWithOverflow">
<TextBlock.Tag>
<MultiBinding Converter="{StaticResource TupleConverter}">
<Binding />
<Binding ElementName="Window"/>
</MultiBinding>
</TextBlock.Tag>
</TextBlock>
Btw: Does someone know how to write local:MainWindow.FInlineProperty="{Binding Name}" in long form? I tried <TextBlock.local:MainWindow.FInlinse>...</TextBlock.local:MainWindow.FInlinse>, but the compiler complains about it.
Update 25.Feb.2017:
I did what you suggested and bound everything to my Attached Property.
<TextBlock TextWrapping="WrapWithOverflow" >
<local:MainWindow.FInlineProperty>
<MultiBinding Converter="{StaticResource GroupConverter}">
<Binding />
<Binding ElementName="Window" Path="MySetup" />
</MultiBinding>
</local:MainWindow.FInlineProperty>
</TextBlock>
The problem with this is, that it is working the first time when the ListBoxItem is created. But updating properties from MySetup does not re-trigger FNamePropertyChangedCallback.
MySetup.ColorString = "green"; // this does not retrigger the callback
MySetup = MySetup.Copy(); // this does retrigger the callback
So currently only assigning MySetup a new copy of itself (changing the reference) triggers callback function again.
That was the reason, why I bound the name property explicitly.
MySetup.ColorString would trigger, if I bind to it explicitly, but I need to bind to MySetup to have all data, so the question is, how to force the binding to execute again, when the bound object itself (reference) has not changed, but something inside did change?
What you actually want is binding between your AttachedProperty and TextBlock.Tag property, so that AttachedProperty is set when Tag changes. But since you are also binding to Name, so I suggest to use MultiBinding for your AP using Name and Tag bindings, thus not depending upon Tag at all.
Try to set the Tag property before you set the attached property. This means that you should also set the attached property using element syntax:
<TextBlock TextWrapping="WrapWithOverflow">
<TextBlock.Tag>
<MultiBinding Converter="{StaticResource TupleConverter}">
<Binding />
<Binding ElementName="Window"/>
</MultiBinding>
</TextBlock.Tag>
<local:MainWindow.FInlineProperty>
<Binding Path="Name" />
</local:MainWindow.FInlineProperty>
</TextBlock>

StringFormat XAML Binding to multiple controls

I have a custom Button type and i cannot change the code. This Button has an property called MyArguments which accepts a string of semicolon separated values.
I have a bunch of TextBoxes on the screen for the user to enter some information.
<TextBox Name="TestTextBox1" />
<TextBox Name="TestTextBox2" />
<TextBox Name="TestTextBox3" />
I want my Button to take these three values and supply them to the MyArguments string property.
If there was only a single TextBox i could use the StringFormat option like this:
<MyButton MyArguments="{Binding ElementName=TestTextBox1, Path=Text, StringFormat='Arguments;{0}' }/>
However you cannot use multiple controls with StringFormat.
I tried using MultiBinding but the MyArguments property gives an error 'The attachable property 'MyArguments' was not found in type MyButton'.
<MyButton.MyArguments>
<MultiBinding StringFormat="Arguments;{0};{1}">
<Binding ElementName="TestTextBox1" Path="Text" />
<Binding ElementName="TestTextBox2" Path="Text" />
</MultiBinding>
</MyButton.MyArguments>
I need this done in pure XAML. No code behind.
Any ideas?
You forgot to add the namespace prefix (e.g. local) to the property:
<local:MyButton>
<local:MyButton.MyArguments>
<MultiBinding StringFormat="Arguments;{0};{1}">
<Binding ElementName="TestTextBox1" Path="Text" />
<Binding ElementName="TestTextBox2" Path="Text" />
</MultiBinding>
</local:MyButton.MyArguments>
</local:MyButton>
This sounds like the parser cannot associate the element syntax property with your element instance. I.e. it thinks you are defining an attached property even though it is supposed to be an instance property.
e.g.
<ListBox ItemsSource="{Binding Data}">
<ListView.ItemTemplate>
<!-- Template -->
</ListView.ItemTemplate>
<ListBox>
Are you referencing the same type? It also looks odd how you have no prefix on your button, or did someone actually abuse the system and compile the assembly to use the WPF namespace?

Text box not showing Red Validation Error in WPF

We are currently writing a GUI application using WPF and .Net4.5.
One of our pages contains a TabControl with custom UserControls as TabItems. These UserControls just contain a list of editable TextBoxes. The Textboxes have a custom ValidationRule that validates the text based on a regular expression. The issue is that these editable text boxes are bound to Properties that get loaded at startup with default values from a text file/database.
I need validation to occur before a text box has focus, or before it is edited, to ensure that the values that were entered in the text file/database were entered correctly. Currently, when I select a tab item the text boxes are not displaying the red validation error box, even though it seems validation is running correctly. Only after I click an item with a Validation error do I see the associated red box.
I am using UpdateSourceTrigger="PropertyChanged" and I can debug and see that the validation code is running at the correct time, but still the red boxes will not display. I even added code to re-fire the 'Property changed' events on the bound properties whenever the TabItem gains focus - but this still does not help. Here is an example of one of the TextBoxes that is not showing the validation:
<TextBox x:Name="TextBox1" Margin="10,5,5,5" Width="150" MaxLength="5" Style="{StaticResource ServiceEntryTextBox}">
<TextBox.Text>
<Binding Path="TexBox1BoundProperty" Converter="{StaticResource DoubleConverter}" UpdateSourceTrigger="PropertyChanged" ValidatesOnDataErrors="True" ValidatesOnExceptions="True">
<Binding.ValidationRules>
<validation:StringRegexFormatValidation RegexPattern="^[0-9]{0,1}.{0,1}[0-9]{1,3}$" ValidatesOnTargetUpdated="True"/>
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
</TextBox>
Is there another piece I am missing?
Can you try placing your TextBox inside an AdornerDecorator? I need to dig out the source for this but I have seen issues before where controls inside a Tab control do not render the validation correctly.
e.g.
<AdornerDecorator>
<TextBox x:Name="TextBox1" Margin="10,5,5,5" Width="150" MaxLength="5" Style="{StaticResource ServiceEntryTextBox}">
<TextBox.Text>
<Binding Path="TexBox1BoundProperty" Converter="{StaticResource DoubleConverter}" UpdateSourceTrigger="PropertyChanged" ValidatesOnDataErrors="True" ValidatesOnExceptions="True">
<Binding.ValidationRules>
<validation:StringRegexFormatValidation RegexPattern="^[0-9]{0,1}.{0,1}[0-9]{1,3}$" ValidatesOnTargetUpdated="True"/>
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
</TextBox>
</AdornerDecorator>
Further help for debugging
I have also seen issues when binding directly to a DependencyProperty. The issue I saw was I was raising INotifyPropertyChanged in order to trigger the validation to be processed (which worked fine in .NET 4.0) however since .NET 4.5 you cannot use INotifyPropertyChanged for triggering validation on a DependencyProperty.

WPF Binding inside Text attribute differs from actual Binding tag syntax in MultiBinding

So the issue is that when I normally bind a single text item to the Text in a TextBlock, the syntax is as follows:
<TextBlock ... Text="{Binding Attributes[StatusDateTime]}" /> //WORKS GREAT!
Now, background is that the DataContext for this part of the app is the output of a 3rd party API. "Attributes" is a collection of KeyValuePair, which is a property of the parent object. StatusDateTime is the key for the value I am returning. The syntax above works just great! So the object would look something like: theDataContextObject.Attributes[StatusDateTime].
BUT, if I need to combine multiple attributes into one TextBlock that's when things get hairy. I have no idea how to access the key from an actual Binding tag:
<TextBlock Grid.Row="0" Grid.ColumnSpan="3" Style="{StaticResource popupText}">
<TextBlock.Text>
<MultiBinding StringFormat="{}{0} at {1}">
<Binding Path="{Attributes[Type]}"/>
<!--<Binding Path="StatusDateTime" />-->
<Binding Path=Attributes[Type]/>
<Binding Path="Type" ElementName="Attributes"/> //the element has no
//name it's just the datacontext
<Binding Path="[StatusDateTime]" />
<Binding Path="Attributes[StatusDateTime]"/>
</MultiBinding>
</TextBlock.Text>
I know the number of examples above does not match the stringformat, I was just pasting examples of my guesses into the multibinding of how to get these values bound.
Apologies if this is a duplicate with another question. I am not sure what to even call this kind of binding where I'm just passing Attributes[StatusDateTime] directly to binding. Keep in mind that Attributes is not the name of an object, it's a property of the object passed to datacontext of the TextBlock's parent control.
So how do I bind to the value of key in the KeyValuePair collection when i have to use a Binding tag inside a MultiBinding?

Binding to 2 string elements?

Is it possible in WPF to bind to 2 elements?
For example I'd like to display something like myserver.com:80 in a textbox.
So to do this I'd like to bind to both a Host field then add a ":" then bind to a port field in my object all for the same label content.
In WPF 4/3.5SP1 you can use a MultiBinding in conjunction with StringFormat:
<TextBlock>
<TextBlock.Text>
<MultiBinding StringFormat="{0}:{1}">
<Binding Path="Host"/>
<Binding Path="Port"/>
</MultiBinding>
</TextBlock.Text>
</TextBlock>
Prior to WPF 4 you can still use a MultiBinding but would need to write your own converter instead.
An alternative to both these approaches is do MVVM and expose a property that does the concatenation for the view, then the view just binds directly to that property.

Categories

Resources