Having a heck of a time getting object property values into textboxes - wpf

I am new to the MVVM design pattern, and I am working on a project to automate shipping processes.
The particular problem that I am having is I have a UserControl (my EditShipmentView) which when it loads, assigns it's ViewModel to its DataContext. The ViewModel is passed a recordID which it uses to pull the entity that represents a shipment. It does this successfully, as I can see it in Mole (visualizer).
Below is a XAML fragment showing the first couple of TextBoxes, and what I thought the bindings should look like.
<local:SnazzyForm Background="#FF318AE1">
<Grid Margin="6,0,0,0">
<TabControl Style="{DynamicResource SnazzyTabControl}" TabStripPlacement="Left" Background="{x:Null}" BorderBrush="{x:Null}" Margin="0,0,0,50">
<TabItem Header="Overview" Style="{DynamicResource TransparentTabItems}">
<Grid Margin="6,0,0,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<StackPanel DataContext="{Binding Path=ShipmentRecord}">
<TextBlock HorizontalAlignment="Left" Text="Contact Info" TextWrapping="Wrap" Style="{DynamicResource TitleText}"/>
<Path Fill="#FFFFB900" Stretch="Fill" HorizontalAlignment="Left" Width="200" Height="2" Data="M0,16.5 L278.5,16.5" Stroke="#FFFFB900"/>
<StackPanel Margin="0,10,0,0">
<Grid Margin="0,16,0,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width=".40*"/>
<ColumnDefinition Width=".60*"/>
</Grid.ColumnDefinitions>
<TextBlock HorizontalAlignment="Right" Text="Company" TextWrapping="Wrap" VerticalAlignment="Top" Style="{DynamicResource FieldLabel}" TextAlignment="Right" Margin="0,2,9,0"/>
<TextBox Text="{Binding Path=CompanyName, Mode=TwoWay, UpdateSourceTrigger=LostFocus, NotifyOnValidationError=True, ValidatesOnDataErrors=True, ValidatesOnExceptions=True}" TextWrapping="Wrap" d:LayoutOverrides="Height" Grid.Column="1"/>
</Grid>
<Grid Margin="0,16,0,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width=".40*"/>
<ColumnDefinition Width=".60*"/>
</Grid.ColumnDefinitions>
<TextBlock HorizontalAlignment="Right" Text="Contact" TextWrapping="Wrap" VerticalAlignment="Top" Style="{DynamicResource FieldLabel}" TextAlignment="Right" Margin="0,2,9,0"/>
<TextBox Grid.Column="1" Text="{Binding Path=ContactName}" TextWrapping="Wrap" d:LayoutOverrides="Height"/>
</Grid>
So, to recap...
EditShipmentView (Inherits from SnazzyForm)
DataContext is EditShipmentViewModel
EditShipmentViewModel.ShipmentRecord is populated (successfully) with a shipment object
ShipmentRecord.CompanyName is a string which obviously should return the name of a company.
Keep in mind this is only my most recent attempt. Previously I have not bound the Stackpanels DataContext and had the Textboxes bound as such "{Binding Path=ShipmentRecord.CompanyName}", and what seems like a hundred different variations. What hair I have left is rapidly receding. Please, think of my hair, send help.
Cory

Show us your code? Chances are your view model is just not notifying the view when it changes. If your bindings are incorrect (not resolved) you will see output to that effect in Visual Studio's debug output window. Check that as well.

Make sure that EditShipmentViewModel (likely culprit) and ShipmentRecord implement INotifyPropertyChanged.
If the data is loaded after the initial view is setup, and the EditShipmentViewModel class doesn't raise a PropertyChanged event for ShipmentRecord, then the View (xaml) will never know to update the binding, and you'll see an empty string.

Related

Access UI Element programmatically UWP

I have some controls in my xaml file of my c++ universal application. I want to access the elements and set some property values.
<PivotItem Header="Home">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="4*"></ColumnDefinition>
<ColumnDefinition Width="3*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<StackPanel Padding="8,8,8,8">
<TextBlock Margin="8" Text="A"/>
<Border Margin="8,0,0,0" HorizontalAlignment="Left" BorderBrush="Gray" BorderThickness="2" Grid.Row="0">
<TextBox x:Name="controlA" x:Uid="controlA" HorizontalAlignment="Left" Width="160" Text="100 kHz" IsEnabled="False" IsReadOnly="True"/>
</Border>
</StackPanel>
</Grid>
</PivotItem>
Is it possible to access my controls programmatically.
I did it finally as below following the accepted answer:
//Code For a text box
for (auto&& child : tstStack->Children)
{
TextBlock^ temp = dynamic_cast<TextBlock^>(static_cast<Object^>(child));
}
In addition to the x:Name name that is promoted to a field in your class, you can walk the tree using element-specific properties. For example, StackPanel->Children returns a collection of child elements that you can add, remove, enumerate, etc.

How to create a ListBox that looks like the Windows Live Tiles?

I want to create a ListBox that looks like the Windows Live Tiles.
This is my XAML:
<ListBox Name="listBox"
Grid.Row="1"
Background="Transparent"
BorderBrush="Transparent"
BorderThickness="0"
Width="Auto" Height="Auto"
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
ItemsSource="{Binding Path=SomeList,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"
VerticalAlignment="Stretch" HorizontalAlignment="Stretch"
VerticalContentAlignment="Stretch" HorizontalContentAlignment="Stretch">
<ListBox.ItemTemplate>
<DataTemplate >
<Grid x:Name="PART_Item" Width="Auto" Height="Auto" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Margin="10">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Image Name="logo" Source="{Binding Path=ImagePath}"
Width="50" Height="50"
Margin="0,0,10,0"
Grid.Column="0" Grid.Row="0" Grid.RowSpan="2"
RenderTransformOrigin="0.5,0.5"
SnapsToDevicePixels="True">
</Image>
<TextBlock Grid.Row="0" Grid.Column="1"
TextAlignment="Left"
FontSize="12"
Text="{Binding Path=SomeName}"
TextTrimming="CharacterEllipsis"/>
<TextBlock Grid.Row="1" Grid.Column="1"
Margin="0,10,0,0"
FontSize="12"
TextAlignment="Left"
Text="{Binding Path=SomeNo}"
TextTrimming="CharacterEllipsis"/>
<TextBlock Grid.Row="0" Grid.Column="2"
TextAlignment="Left"
FontSize="12"
Text="{Binding Path=SomeDescription}"
TextWrapping="Wrap"/>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
How do i change this XAML to look like Windows Live Tiles?
2 Items next to each other for 2 Rows and then 1 Item with a ColumnSpan of 2 and so on it should continue.
I only want to to be in the above mentioned layout.
How would i achieve this?
The image is just for a reference. I want may layout to be like the first 3 Rows.
One easy solution is to use a WrapPanel as the ListBox ItemsPanel. Make your items have the correct dimension (square or rectangle) using DataBinding and give the ListBox the width of two squares.
I'd probably do it with a WrapPanel. Give the ListBox an ItemsPanelTemplate with a WrapPanel in it:
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Horizontal" />
</ItemsPanel>
</ListBox>
Then set your ItemTemplate up so that the size of each item is half the width of the ListBox itself (or the same width, for your example third row). The easiest way to do that is to set the ListBox to a known width, then bind the width of the top-level panel in the DataTemplate to something in the item objects. However, this means the objects need to know how wide they're supposed to be - but if they want to fill the tile sizes properly, maybe that could be seen as a benefit.
Another option is a DataTemplateSelector, but that also needs to have a way of determining if it should deliver a wide or narrow template and it doesn't really have access to information about where in the list it is - it just knows which item to deliver a template for.
If you really want to do it without the items having to know anything about where in the list they're going to appear, I think you're going to have to step back from ListBox and write more of the logic yourself. You might be able to wrangle an ItemsControl into behaving like this, but I think it's more likely you'd need to go back further still and do a full-blown custom control, depending on how much flexibility you actually want.
But judging by your question, I think you'll probably be okay just retemplating the ListBox.

Access ListBoxItem-Controls from code-behind

in my Silverlight 4 application I have a listbox for which I created an itemtemplate:
<DataTemplate x:Key="ItemTemplate">
<Grid Background="{StaticResource BrushCharacteristicListBoxItemBackground}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="10"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBlock x:Name="TextBlockCharacteristicName" Text="{Binding Name}" TextTrimming="WordEllipsis" ToolTipService.ToolTip="{Binding Name}" Margin="6,0,2,0" VerticalAlignment="Center" HorizontalAlignment="Left" />
<TextBlock x:Name="TextBlockSeperator" Text="=" Grid.Column="1" VerticalAlignment="Center" />
<Border Grid.Column="2" HorizontalAlignment="Right" Margin="2,2,6,2" Background="{Binding FunctionState, Converter={StaticResource ConvertCharacteristicFunctionState2Color}}">
<TextBlock x:Name="TextBlockCharacteristicValue" Text="{Binding CalculatedValue, Converter={StaticResource ConvertDouble2Display}}" Padding="2,0" Foreground="{StaticResource BrushCharacteristicListBoxItemBackground}" ToolTipService.ToolTip="{Binding ValueOrFunc}" MaxWidth="72"/>
</Border>
</Grid>
</DataTemplate>
Now I want to access the Controls defined in the template (i.e. TextBlockCharacteristicName) from the code behind. I need this to manually adapt the size of the Controls, which can't be done in an other way.
I hooked into the LayoutUpdated event, but did not found a way to access the controls.
I have tried it with
((StackPanel)ListBoxCharacteristics.GetItemsHost()).Children
which gives me a the list of the ListBoxItems, but there seems to be no way to get the controls from there. Can anyway help me out with this problem?
Thanks in advance,
Frank
Get the small VisualTreeEnumeration chunk of code from this blog: Visual Tree Enumeration.
Now you can find your "TextBlockCharacteristicName" elements with this code:-
foreach (var textBlock in ListBoxCharacteristics.Descendents()
.OfType<TextBlock>()
.Where(t => t.Name == "TextBlockCharacteristicName") )
{
// Do stuff with each Text block.
}

Combo Box with a button in the Items Template

I would like to add a button to the combobox ItemTemplate, that allows the user to click it and remove the clicked item.
This is what i have so far:
<dxe:ComboBoxEdit Name="cboUserCustomReports"
Width="300" Height="Auto"
Margin="0,5,0,5"
ItemsSource="{Binding Path=UserReportProfileList,Mode=OneWay,UpdateSourceTrigger=PropertyChanged}"
EditValue="{Binding Path=UserReportProfileID,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"
ValueMember="UserReportProfileID"
DisplayMember="ReportName"
PopupClosed="cboUserCustomReports_PopupClosed">
<dxe:ComboBoxEdit.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="23"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="{Binding XPath=ReportName}"
VerticalAlignment="Stretch" HorizontalAlignment="Left"/>
<Button Grid.Column="1"
Width="23" Height="23"
VerticalAlignment="Center" HorizontalAlignment="Right">
<Button.Template>
<ControlTemplate>
<Image Source="/RMSCommon;component/Resources/Delete.ico"></Image>
</ControlTemplate>
</Button.Template>
</Button>
</Grid>
</DataTemplate>
</dxe:ComboBoxEdit.ItemTemplate>
</dxe:ComboBoxEdit>
My problem is that my Displaymember is not showing in the TextBlock and only the image of the button template is showing.
Here is a picture of what it looks like:
How do i solve my problem?
Thanks
DisplayMember will not work if you have defined a DataTemplate. However I have seen that you have a TextBlock with a XPath-binding to ReportName. This should do the trick. Check this binding, I assume that there in is the mistake. Check the Visual Studio output-window for binding errors.
<TextBlock Grid.Column="0"
Text="{Binding XPath=ReportName}"
VerticalAlignment="Stretch" HorizontalAlignment
Are you shure that you need an XPath-binding? If you're not sure, try to replace Text="{Binding XPath=ReportName}" through Text="{Binding ReportName}". Maybe this is the only problem.

Silverlight activity control - messing up width and height?

I'm struggling with Silverlights' activity control. I placed a grid inside the activity control and no matter whether it shows "Loading..." or not, the grid doesn't stretch anymore, only the min-values are applied.
After removing the activity-control everything works fine, againg - but I need to use the ctrl.
Did I do something wrong?
Best regards,
rwh
Code:
<Grid x:Name="LayoutRoot" Style="{StaticResource DetailPageLayoutRoot}">
<activity:Activity IsActive="{Binding IsBusy}">
<Grid ShowGridLines="True" MinWidth="200" MinHeight="200" Background="Bisque" >
<Grid.ColumnDefinitions>
<ColumnDefinition MinWidth="50" Width="0.2*"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition MinWidth="50" Width="0.8*"/>
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="0" Margin="1" Background="Beige">
...
</StackPanel>
<controls:GridSplitter Grid.Column="1" VerticalAlignment="Stretch" HorizontalAlignment="Center" Margin="1" Width="4" MinWidth="4" MaxWidth="4"/>
<StackPanel Grid.Column="2" Margin="1" Background="AliceBlue">
...
</StackPanel>
</Grid>
</activity:Activity>
</Grid>
Update:
This control has now(Nov 2009) been incorporated into the Silverlight toolkit. Its been renamed the BusyIndicator. Get it here.
Original Answer:
The latest version of the control fixes this problem.
Download it here: http://www.davidpoll.com/2009/09/14/update-2-displaying-background-activity-in-a-silverlight-ria-application/
I am having the same problem. I think it might be something wrong with the control.
You could set the minwidth/height programmatically.
So innerGrid.minWidth = innerGrid.Parent.Parent.actualwidth;
Not sure if that will work though.

Resources