UWP - AutoSuggestBox customization - validation

I need to support validation on some standard AutoSuggestBox control. So my idea was to customize AutoSuggestBox control by changing it's TextBox to ValidatingTextBox (my implementation of ValidatingTextBox by James Croft). Is that even possible? If yes - how, and if not - what is the alternative?

So my idea was to customize AutoSuggestBox control by changing it's TextBox to ValidatingTextBox
It is not recommended replacing the TextBox of AutoSuggestBox. Some default functionalities might fail because of that. Instead, you can add some function to it. And WinRTXamlToolkit offers a great validation extension to TextBox control.
You can apply this extension to AutoSuggestBox by following steps:
Reference WinRTXamlToolkit in your project. Add reference of WinRTXamlToolkit.Controls.Extensions in your XAML page like below:
<Page
...
xmlns:extensions="using:WinRTXamlToolkit.Controls.Extensions"
...>
Create a copy of your AutoSuggestBox control's style template with Visual Studio. Or you can copy the template from here, and apply it to your AutoSuggestBox control.
Find the TextBox Control in the template. Add extensions:FieldValidationExtensions.Format="the format you need" to it like below:
<TextBox extensions:FieldValidationExtensions.Format="Numeric"
x:Name="TextBox" ScrollViewer.BringIntoViewOnFocusChange="False" DesiredCandidateWindowAlignment="BottomEdge" Header="{TemplateBinding Header}" Margin="0" PlaceholderText="{TemplateBinding PlaceholderText}" Style="{TemplateBinding TextBoxStyle}" Width="{TemplateBinding Width}" Canvas.ZIndex="0"/>
If you want to show validation error message. You can change the panel of this TextBox from Grid to StackPanel and add a TextBlock like below:
<StackPanel>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="Orientation">
<VisualState x:Name="Landscape"/>
<VisualState x:Name="Portrait"/>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<TextBox extensions:FieldValidationExtensions.Format="Numeric"
x:Name="TextBox" ScrollViewer.BringIntoViewOnFocusChange="False" DesiredCandidateWindowAlignment="BottomEdge" Header="{TemplateBinding Header}" Margin="0" PlaceholderText="{TemplateBinding PlaceholderText}" Style="{TemplateBinding TextBoxStyle}" Width="{TemplateBinding Width}" Canvas.ZIndex="0"/>
<TextBlock Text="{Binding (extensions:FieldValidationExtensions.ValidationMessage), ElementName=TextBox}"
Visibility="{Binding (extensions:FieldValidationExtensions.ValidationMessageVisibility), ElementName=TextBox}" />
...
</StackPanel>
Now you get a basic validatingAutoSuggestBox ready for use.

Related

How to make repeating textblocks in Windows Phone 7?

Databinding still confues me and I am not sure how to essential make these controls repeat for each bound piece of data I have.
<Grid>
<TextBlock FontSize="25" Text="this is a header"></TextBlock>
<TextBlock Height="30" HorizontalAlignment="Left" Margin="19,36,0,0" Name="txt" Text="line under the header" VerticalAlignment="Top" />
<TextBlock Height="30" FontSize="25" HorizontalAlignment="Left" Margin="306,9,0,0" Name="textBlock2" Text="530" VerticalAlignment="Top" Width="91" />
<TextBlock Height="30" HorizontalAlignment="Left" Margin="305,42,0,0" Name="textBlock3" Text="30" VerticalAlignment="Top" Width="91" />
</Grid>
If my data source would have a count of 50. I would expect to see 50 of these groupings(I probably need to get a scroll bar though).
Not sure how to do this though. I need some sort of datatemplate I guess? Also "line under the header" should be clickable and highlight.
I think you need to use the control named "ItemsControl". Not a derived class, not a ListBox, just plain simple ItemsControl.
Either in code or in XAML, you set the ItemsControl's ItemsSource property to any collection containing your items.
In XAML (either in VS or Blend, to do it WYSIWYG in Blend you must somehow provide design data) you set the ItemsControl's ItemTemplate to a DataTemplate that contains the XAML subtree you want to repeat for every item in your collection.
Inside the DataTemplate, replace "line under the header" with the Button control, with Content="line under the header", and style it however you want. Then, add CallMethodAction to your button. It only takes 2 clicks in Blend, the first one is on "Assets" window. Specify TargetObject="{Binding}" MethodName="actSubtitleClicked". This way, the framework will call the void actSubtitleClicked() method of the item where user clicked the "line under the header".
For best performance, you should also modify the ItemsControl's ItemsPanel template, replacing StackPanel with VirtualizingStackPanel (again, a few clicks in Blend, the first one is the right click, then "Edit additional templates / ItemsPanel / Edit a copy")

Include controls in a ControlTemplate from another .xaml

I want to create a control which displays an image and a watermark (image or something else) on it.
But the watermark should be loaded from another XAML file in order to let people custom the way the watermark will appear : alignment, opacity, size, nature of the watermark (TextBlock, Image, ...).
For instance I could load my watermark with this appearance
<Border BorderThickness="5" BorderBrush="Aqua" Width="50" Height="50">
<Image Source="play.png" />
</Border>
This code is from my Themes/generic.xaml and MyWatermarkControl (inherits from Control) is the class which contain the code of the control (dependency properties).
<Style TargetType="local:MyWatermarkControl">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:MyWatermarkControl">
<Grid>
<Image Source="{TemplateBinding ImagePath}" />
<Image x:name="watermark" Source="play.png" /> <!--I want this to be loaded from another .xaml-->
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
My search results lead me to add in my ControlTemplate stuff like ContentPresenter, ContentTemplate, DataTemplate : so many results and I cannot understand how do they work but the fact they are nested
You can add a Source property to your MyWatermarkControl then bind the Source property of your embedded Image to this property. For more details see the following tutorial that I wrote:
A Simple Pattern for Creating Re-useable UserControls in WPF / Silverlight

Button Styling in XAML

I have customized the button in this way:
<Button BorderBrush="Transparent" Name="DialButton" Click="DialButton_Click" >
<StackPanel Orientation="Horizontal">
<TextBlock FontSize="43" Name="lblNumber" Margin="0,-5,0,0" />
<TextBlock FontSize="12" Margin="5,20,0,0" Name="lblCharacter" />
</StackPanel>
</Button>
Now, when a user presses the button I want the OnPress state to change the color of the labels. I can do this if it's a simple button by changing the Pressed state. But my label is placed inside a stack panel. How can I change the color in this case? Or in which event can I change the colors of the labels from C#.
You can use the PropertyChangeAction in cases like this. You can find this in the behaviors category on the Assets tab in Expression Blend.
Apply this action on the labels. Change the trigger property to the DataTrigger instead of the default EventTrigger. Bind the trigger to the IsPressed property of the DialButton. Add two PropertyChangeActions per TextBlock and set the Value for one of the to true and the other one to false.
Here's an example for one of them. The other is exactly the same.
<TextBlock FontSize="43" x:Name="lblNumber" Margin="0,-5,0,0" Text="25">
<i:Interaction.Triggers>
<ec:DataTrigger Binding="{Binding IsPressed, ElementName=DialButton}" Value="true">
<ec:ChangePropertyAction PropertyName="Foreground">
<ec:ChangePropertyAction.Value>
<SolidColorBrush Color="Red"/>
</ec:ChangePropertyAction.Value>
</ec:ChangePropertyAction>
</ec:DataTrigger>
<ec:DataTrigger Binding="{Binding IsPressed, ElementName=DialButton}" Value="false">
<ec:ChangePropertyAction PropertyName="Foreground">
<ec:ChangePropertyAction.Value>
<SolidColorBrush Color="{StaticResource PhoneForegroundColor}"/>
</ec:ChangePropertyAction.Value>
</ec:ChangePropertyAction>
</ec:DataTrigger>
</i:Interaction.Triggers>
</TextBlock>
If the i: or ec: isn't working, make sure you've got these lines at the top of your xaml file.
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
xmlns:ec="clr-namespace:Microsoft.Expression.Interactivity.Core;assembly=Microsoft.Expression.Interactions"
You'll need to turn this into a custom control and then you can manage the styling of each component based on the state.
Try this in the click event of button
Button butClicked = (Button)sender;
StackPanel panel1 = (StackPanel)butClicked.Content;
var child1Panel1 = panel1.Children[0] as TextBlock;
child1Panel1.Foreground = new SolidColorBrush(Color.FromArgb(255, 18, 18, 18));
If you're only going to use this button once, probably the easiest way would be to open the .xaml file in Expression Blend, and use Blend to customize the button as you wish, including the state change. If you're using the button in more than one place, do as Matt suggested and make it a custom control (which you can also use Blend to design) that you can reuse.

Items collection must be empty before using error

I using the toolkit which provide the MultiSelectionList control in wp7, I am trying to bind the names to the multiselectItem using the property ItemsSource in C#.
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<StackPanel>
<TextBlock Text="Please select the satellites from the list:-" />
<toolkit:MultiselectList Name="multiSelectionList">
<toolkit:MultiselectItem Content="{Binding Name}" />
</toolkit:MultiselectList>
</StackPanel>
</Grid>
But I got this error.
Items collection must be empty before using ItemsSource.
I tested the service in other parts of the app and it is working with no issues.
Please advise me.Thanks,
You're adding an item to the MultiSelectList when you do:
<toolkit:MultiselectItem Content="{Binding Name}" />
By the time you assign the ItemsSource, which I assume you're doing in the code-behind somewhere, there is already an item in the list (the one above). This is why the error is getting thrown. You could manually clear the list before setting the source, but that's not necessarily considered good practice. What you could do instead is create a DataTemplate, not an actual instance of a MultiSelectItem. I'm not familiar with this control, but try:
<toolkit:MultiselectList Name="multiSelectionList">
<toolkit:MultiSelectList.ItemTemplate>
<DataTemplate>
<toolkit:MultiselectItem Content="{Binding Name}" />
</DataTemplate>
</toolkit:MultiSelectList.ItemTemplate>
</toolkit:MultiselectList>

Looking for a DataGrid Control

I have been trying to find both built-in datagrid control and third party datagrid control for windows phone 7 but with no luck. Can anyone please guide me?
You know you can do this with a simple listbox or (if you want images in your grid) the deferred load Listbox. Here's some simple XAML to show you how:
<ListBox x:Name="myListBox">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<HyperLinkButton Content="{Binding Path=Description}" NavigateUri="{Binding Path=UriForEditingResource}"
<TextBlock Text="{Binding Path=LongDescription}" Grid.Column="1" />
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
In the above example I assume that you setting the myListBox control's ItemSource to a collection of objects whose class contains 3 properties (Description, LongDescription, and UriForEditingResource). There are 2 columns in my example and these columns will be of equal size and they should take over all the available space.
Use Blend to edit these (it will be much easier for you). BTW, I inlined my datatemplate. Blend will typically create a resource for the data template (which means you can re-use datatemplates.
I hope that helps you out some (BTW, the ListBox is not the only control you can do this type of thing with, so study the available controls).
Jay

Resources