i have a controltemplate with a textbox and a button,the button open a sub form to select something and show selected item in the textbox,like this:
<Window.Resources>
<ControlTemplate x:Key="CreateParam">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*"/>
<ColumnDefinition Width="1*"/>
<ColumnDefinition Width="3*"/>
</Grid.ColumnDefinitions>
<Button Content="select" Command="{Binding ShowSpecItemViewommand}" Grid.Column="0" Margin="2"/>
<TextBox Margin="2" Text="{Binding Param}" Grid.Row="0" Grid.Column="1"/>
<TextBlock Margin="5" Text="patameter" Grid.Row="0" Grid.Column="2"/>
</Grid>
</ControlTemplate>
</Window.Resources>
and i have a property in the viewmodel like this:
public string param;
public string Param
{
get
{
return param;
}
set
{
param = value;
RaisePropertyChanged("Param");
}
}
and now i want to create two independent instance of that control in a window,but when i select a value for the first instance,both of them have been changed.should i define two property?and how can i bind them to the control template?
i'm not sure that every one can understand what i mean,so i hope someone edit my question:)
How do you use the Control Template? To which Control do you attach this template? Is it a template for a custom control you have? Is it a template to a known control?
How do you instantiate the DataContext for the Control Template?
While you can implement what you want using ControlTemplate (and a custom control), and if you have many (i.e. much more than two, and all over) instances of your object a ControlTemplate may be the right paradigm, you'll be way better off using DataTemplate, or UserControl. There is more than one way to achieve what you want, but the code below is considered the "canonical" solution:
Say Param is a property of MyVM object. Then your XAML file should be:
<Window
x:Class="SO.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:so="clr-namespace:SO"
Height="200" Width="350"
Title="SO Sample"
>
<Window.Resources>
<DataTemplate DataType="{x:Type so:MyVM}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*"/>
<ColumnDefinition Width="1*"/>
<ColumnDefinition Width="3*"/>
</Grid.ColumnDefinitions>
<Button Content="select" Command="{Binding ShowSpecItemViewommand}" Grid.Column="0" Margin="2"/>
<TextBox Margin="2" Text="{Binding Param}" Grid.Row="0" Grid.Column="1"/>
<TextBlock Margin="5" Text="patameter" Grid.Row="0" Grid.Column="2"/>
</Grid>
</DataTemplate>
</Window.Resources>
<StackPanel>
<ContentControl>
<so:MyVM Param="1234" />
</ContentControl>
<ContentControl>
<so:MyVM Param="5678" />
</ContentControl>
</StackPanel>
</Window>
Related
I'm new to Windows Phone 7.1 development. I work in VB.NET.
I'm working on an application similar with 'How to: Create a Basic Local Database Application for Windows Phone'.
I've managed to write the add and delete code using the sample above.
But the update code... when I return to the page where all the data is displayed, it won't update with the new informations. The information is save (submitted), because when I view the records details in a separate page, they are there.
The XAML page code where all the data is displayed is this:
<ScrollViewer Margin="12,148,12,90" Name="scrollViewerVendors">
<ItemsControl ItemsSource="{Binding AllVendors}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border BorderThickness="1" CornerRadius="12" Margin="2">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<StackPanel Grid.Row="0" Grid.Column="0" Orientation="Horizontal" VerticalAlignment="Center">
<TextBlock Text="{Binding Name}" FontSize="28" />
</StackPanel>
<StackPanel Grid.Row="1" Grid.Column="0" Orientation="Horizontal" VerticalAlignment="Center">
<TextBlock Text="{Binding Address}" />
</StackPanel>
<Button Grid.Row="0" Grid.Column="1" Grid.RowSpan="2"
x:Name="EditVendorButton"
BorderThickness="1"
Click="EditVendorButton_Click">
<Image Source="/Images/AppBar/appbar.edit.rest.png" />
</Button>
<Button
Grid.Row="0" Grid.Column="2" Grid.RowSpan="2"
x:Name="DeleteVendorButton"
BorderThickness="1"
Click="DeleteVendorButton_Click">
<Image Source="/Images/AppBar/appbar.delete.rest.png" />
</Button>
</Grid>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
The update code I've written in the Edit page:
Using DemoAppDB As New DemoAppContext.DemoAppContext("Data Source=isostore:/DemoApp.sdf")
Dim CurrentVendor = From VendorDetails In DemoAppDB.Vendors Where VendorDetails.VendorID = CInt(sVendorID) Select VendorDetails
For Each Vendor In CurrentVendor
Vendor.Name = TextBox1.Text
Vendor.Address = TextBox2.Text
Vendor.ContactPerson = TextBox3.Text
Vendor.Phone = TextBox4.Text
Vendor.Email = TextBox5.Text
Vendor.Notes = TextBox6.Text
Next
'Save changes to the database
DemoAppDB.SubmitChanges()
End Using
The VendorID is passed successfully betweend pages. I've checked.
The database updates, but I can't seem to get the ScrollView record to update. I've also tried with a ListView control.. same result.
The model class Implements INotifyPropertyChanged, INotifyPropertyChanging.
The viewmodel class Implements INotifyPropertyChanged.
If you need any other details, please ask me. Thank you for reading this!
Having had a look at the tutorial I'd say you've missed off
protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
// Define the query to gather all of the to-do items.
var toDoItemsInDB = from ToDoItem todo in toDoDB.ToDoItems
select todo;
// Execute the query and place the results into a collection.
ToDoItems = new ObservableCollection<ToDoItem>(toDoItemsInDB);
// Call the base method.
base.OnNavigatedTo(e);
}
where, for you, you'd be updating AllVendors.
What is happening here is that, after the app has navigated back to the main page it is reloading the ObservableCollection that holds the data.
I have a Grid in a User Control that's placed in a Window that has 2 collections.
I'm looking for a way to get to Collection 2 from within my grid.
I already tried a couple of things:
ItemsSource="{Binding DataContext.Bicycles, RelativeSource={RelativeSource FindAncestor,
AncestorType={x:Type CollectionContainer}}}" />
and
<ComboBox Grid.Column="1" Grid.Row="2" ItemsSource="{Binding RelativeSource=
{RelativeSource FindAncestor, AncestorType=Window, AncestorLevel=1},
Path=DataContext.Bicycles}" DisplayMemberPath="Height" />
and
<ComboBox Grid.Column="1" Grid.Row="2" ItemsSource="{Binding RelativeSource=
{RelativeSource FindAncestor, AncestorType={x:Type Window}}, Path=DataContext.Companies}"
/>
But everytime my combobox ends up empty
When you run your app you should look in your 'Output' window that will tell you the binding errors that come up. So it will give you a clue as to what you're doing wrong.
It looks like you don't need the prefix DataContext. the datacontext of a child control is the datacontext of it's parent by default unless otherwise specified. So if the DataContext of the Window is some ViewModel the UserControl and it's child controls will have the same datacontext.
So you should probably only have to do this:
<ComboBox Grid.Column="1" Grid.Row="2" ItemsSource="{Binding Companies}" />
I'm still pretty new at Silverlight so there might be a way to do this, but I'm just unfamiliar with the terminology...
I basically have this grouping of textboxes and textblocks and I would like to repeat this same grouping whenever the addNew button is clicked. Is there a way to do this by creating some sort of template? Or do I have to add each item individually.
<Grid>
<toolkit:ListPicker Height="70" HorizontalAlignment="Right" Name="listPicker1" VerticalAlignment="Top" Width="56" ItemTemplate="{StaticResource PickerItemTemplate}" FullModeItemTemplate="{StaticResource PickerFullModeItemTemplate}" Margin="0,97,167,0"></toolkit:ListPicker>
<TextBlock Height="33" HorizontalAlignment="Left" Margin="10,7,0,0" Name="tbDate" Text="Date:" VerticalAlignment="Top" Width="266" />
<TextBlock Height="42" HorizontalAlignment="Left" Margin="9,55,0,0" Name="tbItem" Text="Item:" VerticalAlignment="Top" Width="90" />
<TextBox Height="75" HorizontalAlignment="Left" Margin="92,33,0,0" Name="tbItemName" Text="" VerticalAlignment="Top" Width="341" />
<TextBlock Height="42" HorizontalAlignment="Left" Margin="5,118,0,0" Name="tbServing" Text="Serving:" VerticalAlignment="Top" Width="99" />
<TextBox Height="70" HorizontalAlignment="Left" Margin="90,96,0,0" Name="tbServingValue" Text="" VerticalAlignment="Top" Width="75" />
<TextBlock Height="42" HorizontalAlignment="Left" Margin="156,120,0,0" Name="tbUOM" Text="UOM:" VerticalAlignment="Top" Width="60" />
<Button Content="" HorizontalAlignment="Right" Height="63" Margin="0,100,13,0" VerticalAlignment="Top" Width="132" RenderTransformOrigin="0.455,0.286" Style="{StaticResource wp7_buttonAddNew}" x:Name="btnAddNewItem" Click="btnAddNewItem_Click"/>
</Grid>
Thanks!
Merry Christmas!
Yes, you can create a template using a DataTemplate and then very easy using this datatemplate everywhere and whenever you want. You can have a look here: DataTemplate for some examples and full details.
Hint: When you put the DataTemplate in the resources, you can access it and use it many times.
I hope this helps. Cheers.
A User Control is another option that may be worth considering for your requirements.
Here's a walkthrough.
Snowfall (User Control Sample)
My ViewModel has a property called Commands which is of type IDictionary.
For my data grid I have created a ControlTemplate for one of the fields using a button as follows:
<ControlTemplate TargetType="{x:Type igDP:CellValuePresenter}">
<Button Style="{DynamicResource btnRemove}" Width="14" Height="14"
Content="{TemplateBinding Content} "
CommandParameter="{Binding ViewID}"
Command="{Binding Commands[AcknowledgeErrorCmd]}" />
<ControlTemplate.Triggers>
</ControlTemplate.Triggers>
</ControlTemplate>
Clicking on the button does nothing which tells me the binding did not work. However, an unstyled button added to the toolbar of the same window hosting this grid works, binds properly to this command. I guess my question is:
Hw do I bind the command property of a button used in a ControlTemplate to a ViewModel?
TIA.
I am not sure what the problem is but try to debug your solution and look into the output window with Debug selected in the combobox and you will see the errors that occur during binding. Maybe this will help you to the solution.
Provide me the error as a comment on this post if you don't understand it.
I did this instead:
<ControlTemplate TargetType="{x:Type igDP:CellValuePresenter}">
<Border >
<TextBlock Margin="5">
<Hyperlink
CommandParameter="{Binding ElementName=root, Path=DataContext.ViewID}"
Command="{Binding ElementName=root, Path=DataContext.Commands[AcknowledgeErrorCmd]}">
<TextBlock Text="Acknowledge"/>
</Hyperlink>
</TextBlock>
</Border>
</ControlTemplate>
and that works fine. It may be related to the post Viko provided.
I have the following AutoCompleteBox defined inside DataTemplate:
<Window.Resources>
<DataTemplate x:key="PaneTitleTemplate">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinition>
<ContentPresenter Content="{Binding}" />
<toolkit:AutoCompleteBox x:Name="InsertBox" ItemsSource="{???}" />
</Grid>
</DataTemplate>
</Window.Resources>
...
<radRock:RadPane x:Name="pane1" TitleTemplate="{StaticResource PaneTitleTemplate}"/>
Now I'd like to fill it with a list of strings, but I don't know which Binding should I use. The list of strings is an instance variable from the Window. What should I do?
Part of the question is what is your DataContext. If it is the Window itself or is it some other object. If it is the Window then you don't need to specify it in the binding, if it some other object then you must specify that you are using the Window as the binding source. I think the binging you want is as follows (you can remove the ElementName if the Window is the DataContext):
ItemsSource="{Binding StringListName, ElementName=WindowName}"
Obviously replace StringListName and WindowName with the name they actually have in your window.