Binding at Design-Time to WPF Labels, Buttons, etc? - wpf

We're developing a WPF & MVVM application that requires multi-language support. On each control with static text, we're using a converter to do a lookup for the appropriate word for the user's language.
However, this means that each control does not display any text. This causes some irritation for the UI developers at design-time. Is there any way to display design-time text?
For example:
<TextBlock>
<TextBlock.Text>
<Binding Converter="{StaticResource Translator}"
Path="Controller"
ConverterParameter="Search for" />
</TextBlock.Text>
</TextBlock>
How can I make this converter execute at design time to display the translated converter parameter?

First of all I would suggest that you use a markup extension for that. Then you markup would look something like this:
<TextBlock Text="{my:Localize Key=MyLabel, Default='The text you want to be displayed by default'}" .../>
The default text will also be displayed in Blend.
Second of all I don't see the problems with the converter approach as long as the converter returns a valid default text. In other words converters should be executed in design time as well as in run time.

Related

Explicitly setting/ignoring visibility at design-time in VS2013?

I'm designing a form for a complex backing model in WPF. Some of the form controls rely on multiple options being set on the underlying view model, so I've set up for example
<TextBlock.Visibility>
<MultiBinding Converter="{StaticResource AndMultiValueVisibilityConverter}">
<Binding Path="RelevantSystemOption" />
<Binding Path="RelevantLicenseKeyOption"/>
</MultiBinding>
</TextBlock.Visibility>
AndMultiValueVisibilityConverter takes booleans and only makes something visible if they're all true, for reference.
This turns the control's visibility off at design time, which I don't want.
I'm aware of the ability of Expression Blend and design-time attributes to make certain layout determinations that can be ignored at run-time. d:IsHidden isn't being respected, and d:LayoutOverrides doesn't work on Visibility since it's a dynamic property.
I'd rather not dummy up an entire backing model with d:DataContext. I will if I have to, but is there an easier way to just force this particular control and maybe a handful of others to always be visible at design-time?
Just use
DesignerProperties.GetIsInDesignMode(new DependencyObject())
in your multivalue converter to determine if you're in the designer and, if so, return true.
It's okay to use this in a converter in an MVVM application, if you think it might go against the pattern. The converter is a UI concern.
https://msdn.microsoft.com/en-us/library/system.componentmodel.designerproperties(v=vs.110).aspx

How can I suppress a ListView from displaying when content when empty

I have an object that contains an IEnumerable called ValidPhones as a property. When I bind it to a WPF ListView like such:
<ListView DataContext="{Binding ValidPhones}">
<TextBlock>
<TextBlock.Text>
<MultiBinding StringFormat='{}{0}: {1}'>
<Binding Path='Type' />
<Binding Path='PhoneNumber' />
</MultiBinding>
</TextBlock.Text>
</TextBlock>
</ListView>
It still ends up displaying the ": " in the UI even when the Enumerable is empty. Is there a simple way to suppress that from happening?
What backend language are you using with wpf? I'm fairly sure it's either c# or VB.NET. I'm no expert, but I'm pretty sure you can access things like ListViews from code.
EDIT: sorry...I missed the comment at the top. Please mark your threads as closed when you solve the problem so silly people like me don't post useless answers.
Sure! In fact, there are a few options for you to consider.
Option 1: You can always change the visibility of your control to "collapsed" when the list is empty, which will keep your application from rendering it in the xaml. This can be done from your C# code or your xaml. this is a viable solution, but be careful that you don't have other controls that are dependant upon the location of the listview, because setting the visibility to "collapsed" will tell your applicaitonPage not to render the listview at all, which can mess with your layout.
Option 2: You can set up an "IsEmpty" attribute for your iEnumerable, and then bind that attribute to the textblock's text property. If you do it this way then you will need a converter that can return either a blank string or the properly formatted one depending on the value of IEnumerable. This opiton is slightly more complicated, but it has the benefit of leaving your listview alone so that the other controls don't move around.
Please let me know if you need help with either of these options, or if they need clarificaiton :)

Can a WPF converter access the control to which it is bound?

Long version:
I have a simple WPF converter than does date conversions for me. The converter basically checks the date and formats it in dd/M/yyyy format. The converter does some smarts with the handling of the date which means that the user could type "23061971" and the value will be converted to "23/06/1971".
All this is trivial and working. The problem is that when I update the value, it does not update the caret position. Assume "|" is the caret and the user types "23061971|" then a millisecond later it is updated to "230619|71".
What I'd like to do is detect if the caret at the end of the value - if so, shift it to the end of the edit field once the new value has been updated. In order to do this, I'll need access to the edit control to which the converter is attached.
Short version:
From A WPF converter, can I get a reference to the control that is bound to that converter?
Here is an excellent article on how to get direct access to the control from within a converter: http://social.technet.microsoft.com/wiki/contents/articles/12423.wpfhowto-pass-and-use-a-control-in-it-s-own-valueconverter-for-convertconvertback.aspx
Essentially:
<MultiBinding Converter="{StaticResource MyConverter}" >
<Binding RelativeSource="{RelativeSource Self}" Mode="OneTime"/>
<Binding Path="MyValue2" />
</MultiBinding>
in the converter values[0] will be your control, ready for casting and values[1] would be the data that you are binding.
In a ValueConverter you can't get access to the control - however you can get access if you use a multibinding with a multivalueconverter.
In the multibinding the first binding is your binding as now - without the converter. The second binding you bind to the control itself - there you go acces to the control.
I have used this approach to gain other things also - you can make "dummy" bindings to properties you want to trigger updates, i.e. if you bind to the control itself you will only get updated if it changes, not if a property does - so create dummybindings for those.
You can send the control with the MultiBinding like this.
<TextBox Height="100" x:Name="textbox1" DockPanel.Dock="Top">
<TextBox.Text>
<MultiBinding Converter="{StaticResource MultiConverter}">
<Binding ElementName="textbox1" Path="." />
</MultiBinding>
</TextBox.Text>
</TextBox>
I don't thknk a converter has any way to get at the control that is using it. It is only a simple piece of logic that converts one object to another object.
However, in you case, perhaps you can trap the change event and then manually move the caret. If you think about it, caret position is strictly a view concern; it has nothing to do with converters or the data. You should not burden view-controller logic with it. You should definitely not burden converter logic (which is classified under utility classes) with it.

WPF> Using RadioButtonList style. I want to display user friendly enum strings. how?

I want to display all the possible enum values as Radio buttons. I am using popular RadioButtonList style to display the radiobutton from my enum using DataProvider in a Listcontrol. I can get all the radio buttons but the text appear with the radio button is not user friendly. I am using the following method.
http://social.msdn.microsoft.com/forums/en-US/wpf/thread/5137aabc-bb3a-478a-9438-bc93dd9cc0ac/
I want to show "A ball" instead of "a" and "B ball" instead of "b"
I thought about using converter. But where to use convert. Or any other way to display user friendly values?
As this style is very common, thats why I am not writing whole code. If anything not clear, please ask. I have already invested about 5 hours on this problem.
Change the empty ContentPresenter to the following binding:
<ContentPresenter>
<ContentPresenter.Content>
<Binding Converter="{StaticResource EnumToUserFriendlyName}"/>
</ContentPresenter.Content>
</ContentPresenter>
Then in the converter you can check the enumerated value and return a more user-friendly name.

How to determine WPF SelectedItem for a window

I have a WPF app with many list based controls in a window, which all are bound to different CollectionViews.
At the window level is there a way to get the current selected item for the currently in focus list based control? I know I can do this with some fairly trivial code by looking for the in focus element but does WPF support this as a concept out of the box?
Something like Window.CurrentSelectedDataItem would be great. I am looking into using this as a way to centralize command management for enabling disabling commands based on a current selected data item.
I don't think that there is a property like you specify, but as an alternative you could register a ClassHandler for the ListBox.SelectionChanged event in your Window class:
EventManager.RegisterClassHandler(typeof(ListBox), ListBox.SelectionChanged,
new SelectionChangedEventHandler(this.OnListBoxSelectionChanged));
This will get called whenever the selection changes in any ListBox in your application. You can use the sender argument to determine which ListBox it was that changed its selection, and cache this value for when you need it.
I haven't tried this, but you could try using a MultiBinding with a converter to get to the correct item:
<MultiBinding Converter="{StaticResource coalesce}">
<MultiBinding.Bindings>
<MultiBinding Converter="{StaticResource nullIfFalse}">
<MultiBinding.Bindings>
<Binding ElementName="List1" Path="HasFocus" />
<Binding ElementName="List1" Path="SelectedItem" />
nullIfFalse returns the second parameter, if the first is true, null otherwise. coalesce returns the first non-null element.

Resources