Use Table without messing with DataGrid - c#

Is it possible to make a table having cells bound to several objects (for example, textboxes) without making use of DataGrid?

Example:
<TextBox Text="{Binding Path=FileName}" Width="300"></TextBox>
The DataContext for the textbox's container should contain a Property named FileName
You should note that your property should be wired to notify when it is changed. See the following for more information:
http://msdn.microsoft.com/en-us/library/system.componentmodel.inotifypropertychanged.aspx

Related

WPF Combobox - Displaying Count in Label

I've got a simple WPF ComboBox, displaying Orders/Positions on the Financial Markets.
<ComboBox Name="TradeDropDown"
HorizontalAlignment="Stretch"
VerticalAlignment="Top"
ItemsSource="{Binding Path=ActiveOrders}"
DisplayMemberPath="OrderLabel"
SelectedItem="{Binding Path=SelectedOrder, Mode=TwoWay}" IsSynchronizedWithCurrentItem="True" />
I need to see at a glance how many items are in the list. I've added a TextBlock above with summary information.
I don't like it, and would prefer to have the items in the dropdown listed like:
(1/2) Working Short 425K
(2/2) Filled Long 979K
etc - and have the 1/2 numbers correctly update as items are added and removed from the list.
The Items are stored in a BindingList.
Is there an easy way to do this?
Is there an easy way to do this?
Add another property to the class where the OrderLabel property is defined that returns a string like "(1/2) Working Short 425K" and set the DisplayMemberPath property of the ComboBox to the name of this property.
Make sure that the class implements the INotifyPropertyChanged interface.
You then set the new property to a new value and raise the PropertyChanged event whenever you want to update the label in the ComboBox.

Getting changed data using binding in WPF/C#

I have a basic project in WPF.
All it does it retrieve / update products.
As shown in the image below, the user enters an ID, the data is then displayed according to it, and the user is able to change the data and click 'Save Product' to save it to the database.
The GetProduct(int id) function retrieves a product by the ID provided.
The SaveProduct() function saves the changed fields.
Also, there are two DataTemplates:
1) For the ProductModel - includes 3 textboxes: ProductId, ProductName, UnitPrice.
2) For the ProductViewModel - includes the save/get buttons + a textbox for the user to enter the id of the desired product.
What I'm trying to do is get the changed data when a user clicks the 'Save Product' button.
The most ideal way in my opinion, is to use Binding.
Each textbox is already binded, but I have no idea how to get the binded data.
Here is an example of a binded textbox in the FIRST DataType (ProductModel):
<TextBox Grid.Row="0" Grid.Column="1" Text="{Binding ProductId}" Margin="5" Width="150" />
There is one for each of the following properties: ProductId, ProductName and UnitPrice.
IMPORTANT!: The Get/SaveProduct() functions are in the ProductViewModel class, while the actual product class is - you guessed it - ProductModel. The ProductViewModel class holds a variable that contains the current product displayed.
This is the button that's used to save the info - it is written in the SECOND DataType (ProductViewModel):
<Button Content="Save Product" DockPanel.Dock="Right" Margin="10,2" VerticalAlignment="Center" Command="{Binding Path=SaveProductCommand}" Width="100" />
The SaveProductCommand command simply fires the SaveProduct() function.
I have a few questions regarding this whole subject:
What does it mean when a binding is used like this : {Binding ProductId} ?
The default binding mode for textboxes is TwoWay as far as I remember. But in this case, ProductId/Name + UnitPrice are not dependency properties, therefore is it right that the binded values do not update/sent back when the text in the textboxes is changed? (Since there isn't an event attached to it...)
A data context was never configured in my project, but all of the "binding tags" in my XAML pages don't seem to have a defined source. Could it be that the source is actually the DataType in the DataTemplate that includes the binded objects?
The SECOND DataTemplate (the ProductViewModel one) has this ContentControl tag: <ContentControl Margin="10" Content="{Binding Path=CurrentProduct}" />.
What is it's purpose?
If a TwoWay binding were/does occur, how do I get the values from within the SaveProduct() function? Do I just refer to, say CurrentProduct.ProductName to get the changed name?
Much thanks to everyone who takes their time to answer - I appreciate it so much!
What does it mean when a binding is used like this : {Binding
ProductId} ?
The specific control property you have this binding set on is going to look for the ProductId property on the object set as the DataContext and set the propertys value in the control accordingly.
The default binding mode for textboxes is TwoWay as far as I remember.
But in this case, ProductId/Name + UnitPrice are not dependency
properties, therefore is it right that the binded values do not
update/sent back when the text in the textboxes is changed? (Since
there isn't an event attached to it...)
You do not need to make the properties within your object a DependencyProperty for TwoWay binding to occur.
A data context was never configured in my project, but all of the
"binding tags" in my XAML pages don't seem to have a defined source.
Could it be that the source is actually the DataType in the
DataTemplate that includes the binded objects?
The bindings being set within your XAML will use the object stored within the DataContext, thus if you do not explicitly set the DataContext of the view, it will be null. You should note however that the DataContext is inherited from its parent. If you are in fact setting the content by using say, CurrentProduct, then all the properties will be available to bind to per your Product type.
The SECOND DataTemplate (the ProductViewModel one) has this
ContentControl tag:
<ContentControl Margin="10" Content="{Binding Path=CurrentProduct}" />
What is it's purpose?
It is acting as the container of your CurrentProduct, which can contain one and only one item.
If a TwoWay binding were/does occur, how do I get the values from
within the SaveProduct() function? Do I just refer to, say
CurrentProduct.ProductName to get the changed name?
Without seeing the entire application, my guess is that the ContentControl is being set to the CurrentProduct and your TextBox, etc.. are all bound to the respective properties, such as CurrentProduct.ProductId, etc... The product which you want to save is in fact the CurrentProduct. When you call save within your ViewModel, you simply access the CurrentProduct and persist it as needed, where CurrentProduct.PropertyName will contain the changes which were propagated from the UI.

Access to embedded WPF controls in xaml

Lets say I got the following user control:
<UserControl x:Class="MyUserControl">
<tk:DataGrid>
<tk:DataGrid.Columns>
<!-- some columns -->
</tk:DataGrid.Columns>
</tk:DataGrid>
</UserControl>
Actually, I can't define what columns the data grid should have, since I need to use this control in many places, with different columns. Here is what I want to do:
<UserControl x:Class="MyPanel">
<ui:MyUserControl>
<Columns>
<!-- columns that will go into the data grid -->
</Columns>
</ui:MyUserControl>
</UserControl>
Is it possible to achieve this?
P.S: DataGrid.Columns is readonly, it is not possible to bind it to something else.
You can expose a depenency property on the UserControl called Columns which can bind to an internal DataGrid. You would access the property via <ui:MyUserControl.Columns> of course.
As #H.B. said in his solution, you should expose your own dependency property, but just performing binding wouldn't work, since the Columns property is read-only.
What you need to do is handle this in your dependency property's OnChange callback and add/remove columns as necessary. You'll also need to register to your dependency property's CollectionChanged event and possibly the grid's Columns CollectionChanged as well to synchronize the two properties.
Unfortunately, I don't think there's a XAML-only solution for this.

TextBlock width binding to GridView

On my XAML page I have a text block with following binding:
<TextBlock Width="{Binding ActualWidth, ElementName=SessionList, Mode=OneWay}" ... />
This binds to a grid view:
<GridView x:Name="SessionList" ItemsSource="{Binding Sessions}"... />
Now when the page first loads and data is available, the text block will be visible and have the correct width. When the page loads and there is no data, the text box will not be visible because of the bound width.
But ... when I load up data in the background and after a while the data comes in (through MVVM) the list will be show, but the text block width will not change accordingly, and setting it as TwoWay has no effect.
Any ideas/tips?
ActualWidth is not a property that you can bind to within WinRT. Not sure if you are showing static text or bound text. If bound text and data is same as GridView has then it should go away if data is null. If static data, then use a ValueConverter to set the visibility of the TextBlock based on the data being null/empty
Binding issues like this are usually caused by properties that are not bindable, i.e. they are not dependency properties and/or do not implement INotifyPropertyChanged. Whatever. I use a Attached Dependency Property or, if that does not cover enough, a behavior. Now behavior are not included in WinRT, but that problem has already been addressed ;-)

Silverlight Misc. Questions

I am still new to silverlight and would like to ask few questions that relate to performing common tasks in silverlight that you used to do in asp.net programming (btw, I am using silverlight 4):
In silverlight, how do you access a public property on a user control in a databinding expression (without setting datacontext on the control itself)? For example, let us use a datagrid with ItemSource bound to some collection but you want to also databind to a value defined by a property your user control using the databinding expression, perhaps using 'Source' property. In asp.net you could access any public property/method using <%# expr #>.
In asp.net when a postback control was clicked and raised an event you were able to access the row in the event handler via event args and use FindControl() to find any control in the row. What's the equivalent process in silverlight?
I know how to do get the row using DataGridRow.GetRowContainingElement() but then when I use row.FindName() I can't find another control in the same row by its name, I get null back. I found postings to do something like: grid.columns[colIndex] but that's error prone since you are using index to reference the column and then you have to get the cell content to access the control you after (cell.GetCellContent(row)). It is also not universal, the above illustrated how to do it in a datagrid.
In asp.net there's OnDataBind event you can handle on majority controls, is there something equivalent in silverlight?
to create another property like the datacontext for your user control, you can create your own custom dependency property.
I would use the SelectionChanged event instead of the mouse click. it will easily tell you what row was "Added" when the user clicked the row.
At this time, no, you do not have a DataContext_Changed event in silverlight. BUT you can create your own by creating a custom dependency property, which will set the data context, and raise your own custom events. (not really sure why they didn't implement that originally, its in the WPF world).
edit to bind a property to the current control, use the following format:
Property="{Binding RelativeSource={RelativeSource Self}, Path=YourCustomProperty}"
for example, here is a textbox, where its text property is bound to its ID property:
<TextBox Height="16" HorizontalAlignment="Left" Margin="97,105,0,0" Name="txtName"
VerticalAlignment="Top" Width="120"
Text="{Binding RelativeSource={RelativeSource Self}, Path=Name}"/>

Categories