Several Wpf controls have no visual representation unless they have some data (ItemsControl for example). So to view their layout in the Visual Studio designer you need to use the DesignData XAML extension to populate them with something that can be rendered. A common usage of these controls is to define several implicitly typed datatemplates so that the control can display a variety of types.
However, it seems to me that the designer has little or no support whatsoever for this most simple of layouts making it all but useless to us, but I'm hoping I'm wrong and that I've just overlooked something. Here is how it seems to me (xmlns namespaces omitted for brevity).
<UserControl
d:DataContext="{d:DesignData Source=/CustomersDesignData.xaml}">
<Grid>
<ItemsControl>
<ItemsControl.ItemTemplate>
<DataTemplate>
<ListBoxItem>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding FirstName}"/>
<TextBlock></TextBlock>
<TextBlock Text="{Binding LastName}"/>
</StackPanel>
</ListBoxItem>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
</UserControl>
The above works in that the designer correctly displays the sample data enabling one to verify the layout. But there is no implicit datatyping making this approach useless for displaying multiple types.
<UserControl
d:DataContext="{d:DesignData Source=/CustomersDesignData.xaml}">
<Grid>
<ItemsControl>
<ItemsControl.Resources>
<DataTemplate DataType="{x:Type local:Customer}">
<ListBoxItem>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding FirstName}"/>
<TextBlock></TextBlock>
<TextBlock Text="{Binding LastName}"/>
</StackPanel>
</ListBoxItem>
</DataTemplate>
</ItemsControl.Resources>
</ItemsControl>
</Grid>
</UserControl>
The above works fine at runtime and additional implicitly datatyped tempates can be added enabling the control to display multiple types. The gorilla sized fly in the ointment though is that the designer dumbly displays the raw ToString() output, making this approach useless for developing the UI.
Furthermore it seems to make no difference whatsoever where you define the template, put it in UserControl or App resources and the result is the same, nada. As far as I know there is no way to support any form of conditional compilation in XAML and the type's constructor is not run by the designer so even a code behind solution seems unlikely.
We are at the start of a project porting a sizable data application that is going to require us to design about 200 UI's, and many of these UI's are buried deep in the application. The lack of any means of being able to develop these UI's with design data displayed is already hurting our productivity and is likely to get much worse.
Has anyone else encountered a similar issue and what solutions or workarounds exist?
The solution to this problem, in my experience and in my opinion, is to set the IDE to "Open XAML files in XAML view".
In other words, don't use the designer.
If you 'need' to use the designer then open Blend, draw the designs, and then integrate them into your application. You can see each View individually. You just need to view the consolidated layout within the context of a running application. The most productive WPF and Silverlight developers I've worked with use this approach.
Related
I have an itemscontrol with repeating stackpanels with child controls. Each stackpanel contains a textblock I wish to be editable. The project has a MVVM framework implemented what makes this a difficult one. I think the best way is to make a button inside each stackpanel that is connected to a BooleanToVisibilityConverter. This converter is connected to a textblock and inverted to a textbox. So it shows one of the two. The problem is I am having trouble realizing this solution.
If i bind the visibility to the back-end then this will result in showing all the textblocks or non. The solution i have now is as following:
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
<CheckBox x:Name="DisplayBox" IsChecked="False"/>
<TextBlock Visibility="{Binding ElementName=DisplayBox,
Path=IsChecked,
Converter={StaticResource BoolToVis}}">
<Run Text="{Binding Title}"/>
</TextBlock>
</StackPanel>
So my question is:
Is there a simple way to implement an editable textblock with only XAML binded to each control? Or do I need to implement a way that connects it to the back-end.
this will result in showing all the textblocks
Using the name of a control to bind to it is a strategy I use quite often, but this time it has let you down for you are in a repeating template. For using that binding process in a template makes the selection becomes global and not local.
So one strategy is to use a RelativeSource binding and point to the local parent (the checkbox) such as:
<CheckBox IsChecked="False">
<TextBlock Visibility="{Binding IsChecked,
Converter={StaticResource BoolToVis},
RelativeSource={RelativeSource Mode=FindAncestor,
AncestorType={x:Type CheckBox}
}
}">
<Run Text="{Binding Title}" />
</TextBlock>
</CheckBox>
As an aside and don't read this the wrong way,
project has a MVVM framework implemented what makes this a difficult one.
MVVM is simply a way to separate code concerns (operations, classes and GUI) and frankly shouldn't necessarily come into play when dealing with Xaml bindings.
Whether the data resides on a VM or the page is immaterial for what is required is to set the page's datacontext or the control's datacontext with a valid class instance to be reflected by the binding system. Nothing more nothing less.
For new programmers there are a lot of concepts such as MVVM and binding and that learning curve is significant. My advice is that the buzzword used to be Three tiered systems..now its MVVM or MVC but in the end they all do much of the same, just separation of those programming concerns.
In our application we dynamically load some DataTemplates at runtime based on use cases. And these DataTemplate refers to another layer of DataTemplates, and this can go on for two or three layers.
Since there are many DataTemplate definitions, we might miss defining one of lower layer DataTemplates.
The bad thing is that VisualStudio does not warn the missing DataTemplate and the build goes OK without related warning and the exception throws at run time.
Without compiler aid, it's purely human diligence to get bug-free code.
Any tools can help to detect undefined but referenced DataTemplate?
Thanks a lot.
For example the following simplifed XAML illustrate the problem. Layer1 DataTemplates refers to Layer2 DataTemplates. Layer1_0x00010D83_Layer2List_0x00010712_0x00010719 is loaded dynamically at run time, it refer to Layer2_0x00010712 and Layer2_0x00010719. If Layer2_0x00010719 is not defined, then the compiling goes OK, but throws error at run time.
<DataTemplate x:Key="Layer2_0x00010712">
<StackPanel >
<TextBlock Text="{Binding Converter={StaticResource NameConverter}}"
Style="{StaticResource NameTextBlockStyle}" />
</StackPanel>
</DataTemplate>
<DataTemplate x:Key="Layer1_0x00010D83_Layer2List_0x00010712_0x00010719">
<local:Layer1Border x:Name="" Layer1ID="0x00010D83" >
<Grid>
<local:Layer2Border Grid.Column="0" Grid.Row="1"
<Button Content="{Binding}" ContentTemplate="{StaticResource Layer2_0x00010712}"/>
</local:Layer2Border>
<local:Layer2Border Grid.Column="1" Grid.Row="1"
<Button Content="{Binding}" ContentTemplate="{StaticResource Layer2_0x00010719}"/>
</local:Layer2Border>
</Grid>
</local:Layer1Border>
</DataTemplate>
Is there a open source WPF control that looks like ListView and supports inline edit? More specifically, a cell in the ListView should be editable when you double click on it, and the edit result should be automatically saved unless you hit ESC afterwards.
I don't know of any WPF controls that do what you are looking for, but that is not indication that they don't exist. If you checkout the WPF Toolkit on Codeplex, you may find something and there are a lot of OSS projects for WPF controls on Codeplex in addition to the toolkit.
You can create one very easily taking advantage of the WPF content control model. Here is an example of a ListBox with a set of controls used to represent the objects bound to the list.
<ListBox x:Name="sampleListBox"
Width="500">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid>
<GridRowDefinitions>
<RowDefinition Height="25"/>
<RowDefinition Height="25"/>
</GridRowDefinitions>
<TextBox Grid.Row="0" Source="{Binding EditableProperty1}}"/>
<TextBox Grid.Row="1" Source="{Binding EditableProperty2}"/>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
You can control the editability of the controls with Styles so that when the ListBox item is selected, the internal controls are editable but otherwise, they are not. I don't have access to my work laptop atm so I can't provide a style example but there are a lot of materials on the web that can help you. And if you have Expression Blend 4, it has a lot of functionality that can really help you when you are styling your own controls.
I have a databound ListBox with an ItemTemplate, following this example:
<ListBox ItemsSource="{Binding Path=FlightHeadings}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding Path=Identifier}" />
<TextBlock Text="{Binding Path=Name}"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
The ItemsSource databinding works; the ListBox displays all the items in the FlightHeadings property of the context.
However, the ItemTemplate is ignored. Instead of displaying each item as consisting of two TextBlocks, each item is instead displayed simply as its ToString() representation.
FWIW, I'm running Silverlight 4.0 on VS 2010, serving the test page with Cassini. I suspect I'm missing something very simple in the above XAML but I can't tell what it is; any advice would be greatly appreciated.
Turns out that the XAML is okay; the issue is that an old build of the XAP file was being displayed.
Purging the browser cache, restarting the development web server, and restarting the browser fixed the problem.
The following code works fine in WPF.
In Silverlight it gives me the error **Invalid attribute value {Binding ElementName=WhichNumber, Path=SelectedItem.Content} for property Text. **
How can I get this to work in Silverlight?
<ComboBox x:Name="WhichNumber" Width="100" HorizontalAlignment="Left" Margin="10" SelectedIndex="0">
<ComboBoxItem Content="One"/>
<ComboBoxItem Content="Two"/>
<ComboBoxItem Content="Three"/>
</ComboBox>
<TextBlock Text="{Binding ElementName=WhichNumber, Path=SelectedItem.Content}"/>
Silverlight doesn't support Relative Binding (binding the attribute of one element to the value of another element's attribute value) while WPF has full support for that kind of binding.
Or you could move to Silverlight 3 which introduces UI element to element binding :)
For some reason (why they did this is beyond me), the syntax is slightly different, instead of writing when using WPF:
<TextBlock Text="{Binding ElementName=WhichNumber, Path=SelectedItem.Content}"/>
you would write with Silverlight 3:
<TextBlock Text="{Binding ElementName=WhichNumber, SelectedItem.Content}"/>
so without the 'Path=' part.
Unfortunately the Silverlight people at Microsoft have a tendency to make small changes to syntax and other things, rather than striving for easy code reuse across WPF and Silverlight.