Cannot connect a slider control to GridLabels using HelixToolkit - wpf

I am trying to use GridLabels to display time in a model:
GridLabels.Add(new BillboardTextItem
{
Text = String.Format("{0} {1} {2}", "Time = ",
Well.TubeAnimTime.ToString("N0"), "Sec"),
Position = new Point3D(0, 0, 500),
WorldDepthOffset = 100
});
I tried to test this functionality using a Slider Control:
<StackPanel>
<TextBlock Text="Animation" />
<Slider x:Name="AnimationSlider" Value="{Binding Well.TubeAnimTime}"
ToolTip="{Binding ElementName=AnimationSlider, Path=Value}"
Minimum="0" Maximum="100" Width="100" Margin="10"/>
</StackPanel>
Although the label displays OK and responds to all movements and zooming, it does not respond to the Slider. I know Slider works ok because other elements in my model responds to it.
I tried to change the biding mode to TwoWay in:
<h:BillboardTextGroupVisual3D Background="Gray" Foreground="White"
FontSize="12" Offset="2,2"
Padding="1" Items="{Binding GridLabels, Mode=OneWay,
UpdateSourceTrigger=PropertyChanged}"
IsEnabled="{Binding IsChecked, ElementName=FreezeAxisLblsCheckBox}" />
VS 2017 does not allow me as the property seems to be readonly.
I really like Helix Toolkit but I seem to be slow learner. Anyone can explain why the binding with the Slider does not work. Or is there any easier way to display the time parameter in a distinct box like GridLabels?
I.Konuk

Neither BillboardTextItem nor BillboardTextGroupVisual3D.Items is Observable. So the binding will not work.

Related

How do I use a user's name, entered in a textbox in MainWindow, in textblocks in several other windows?

When a user enters his/her name in 'whatsYourNameTextbox' in my MainWindow, I want that name to be used in Textblocks in other windows in my app. I can get it to work for a Textblock in the MainWindow, using this code:
<TextBlock Grid.Column="0" Grid.Row="3" Grid.ColumnSpan="2"
x:Name="doYouWannaPlayTextblock"
FontFamily="Segoe Print"
FontSize="16"
FontWeight="SemiBold"
Foreground="Red"
Padding="20"
Visibility="Hidden"
TextAlignment="Center"
TextWrapping="Wrap" Margin="0,0.4,0.2,-25">
Hi,
<TextBlock Text="{Binding Path=Text, ElementName=playerNameTextbox}"/>
- it's good to see you. Would you like to play 'Tables'? If so, just click the 'Choose Game' button.
</TextBlock>
But when I use the same code in the 'ChooseGameWindow' (and, I assume, in other windows I plan to put into the app) the user's name doesn't appear but no error is thrown up. Here's the code in the 'ChooseGameWindow':
<TextBlock
FontFamily="Segoe Print"
FontSize="16"
FontWeight="SemiBold"
Foreground="Red"
Padding="20"
Visibility="Visible"
TextAlignment="Center"
TextWrapping="Wrap" Width="293" Height="71">
Hi
<TextBlock Text="{Binding Path=Text, ElementName=playerNameTextbox}"/>
. Click a 'Play Me' button.
</TextBlock>
I'm guessing that I need to reword the binding to refer to something like, 'MainWindow.whatsYourNameTextbox' (or similar) but haven't been able to work out how to do it. Thanks in anticipation.
You can use event aggregator to communicate between view models.
Edit
private void ChooseGameCommandHandler()
{
var window = new MainWindow();
window.DataContext = new MyViewModel(TextBoxValue);
window.Show();
IsVisible = false;
}
Full sample code here

How to handle Validations on Custom Control

I recently wrote my first custom control, an autocomplete textbox. Its Controltemplate consists of something like this
<Grid >
<Border/>
<TextBlock x:Name="Label"/>
<TextBox x:Name="TextLabel"/>
</Grid>
The first Textblock is used as a Label, the second one shows the content. The TextLabel binds on an Object, let's call it Customer If the underlying search doesn't find a Customer object, I want to show the errortemplate. When defining the TextLabel like this
<TextBox x:Name="PART_Editor"
HorizontalAlignment="Stretch"
VerticalAlignment="Center"
Validation.ErrorTemplate="{DynamicResource ValidationErrorTemplate}"
Style="{StaticResource TransparentTextBoxStyle}"
Text="{Binding Path=Text, RelativeSource={RelativeSource Mode=TemplatedParent},
Mode=TwoWay, ValidatesOnNotifyDataErrors=True,
NotifyOnValidationError=True,
ValidatesOnDataErrors=True,
UpdateSourceTrigger=PropertyChanged}" >
</TextBox>
the Validation is made and the error template of the textbox is shown. Unfortunately the Red Border is only around the inner TextBox and not around the whole custom control which looks just not good.
I was wondering how to achieve two things:
How can the ErrorTemplate of the CustomControl be triggered when one of the child-validations fail?
Do I have to specify all these NotifyOnValidationerror properties or is it possible to catch all errors on entity level and show the same ErrorTemplate
If you need additional Information, please just ask

Binding a ComboBox selection to the background color of a border.

Please forgive my ignorance. I am new to vb.net and WPF. I have a comboBox that has a list of colors like this. By the way this is in WPF.
Public Sub New()
InitializeComponent()
cmbColors.ItemsSource = GetType(Colors).GetProperties()
End Sub
In the XAML the comboBox is created as follows:
<ComboBox Name="cmbColors" HorizontalAlignment="Left" Margin="29,35,0,0"
Grid.Row="1" VerticalAlignment="Top" Width="120">
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Rectangle Fill="{Binding Name}" Width="16" Height="16"
Margin="0,2,5,2"/>
<TextBlock x:Name="cmbColorsText" Text="{Binding Name}"/>
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
What I'm trying to do is when the program is run start with a beginning background color of grey, and when a new background color is selected from the comboBox the back ground will update.
Here's the XAML of the element that I'm trying to bind to the selection.
<Border BorderBrush="{x:Null}" Grid.Column="1" Grid.Row="1" Background="{Binding Text, ElementName=cmbColors}">
<TextBlock Text="PRACTICE" Style="{StaticResource linkButtons}"/>
I have gone through every (string) type in the property window for the border>background>create binding>Element>comboBox and for some reason (that I can't determine) I have either missed the appropriate one or am looking at this the wrong way.
Thank you in advance!!!
You are binding the Background to a string, but the Background will need a ColorBrush. So, if your combo ItemsSource already contains items that are of ColorBrush then you can just bind to SelectedItem rather than Text.
Or you can use a converter in your Background binding, that takes the string and returns a SolidColorBrush, say.
Change the binding to
<Border BorderBrush="{x:Null}" Grid.Column="1" Grid.Row="1" Background="{Binding SelectedItem.Name, ElementName=cmbColors}">
<TextBlock Text="PRACTICE" Style="{StaticResource linkButtons}"/>
The Text property of the ComboBox is returning the result of the ToString() method of the PropertyInfo object, so for instance if you select Black, it will be "System.Windows.Media.Color Black" and won't be parsed as a valid color.

Binding OnwayToSource not working as expected - what alternatives?

Ive a business object - call it Fish (not derived from anything ie not a DependancyObject) that is displayed in a ListBox using a DataTemplate. Else where in code I need to know the rendered width of the TextBlock part of the Fish DataTemplate through a reference to a Fish. No problem I thought. I added a width and height properties to Fish class and in my data template I bound the TextBlock width/height to these using Mode=OnwayToSource.
Problem: the Width/Height are always NaN when setting my Fish.width/heigh properties. I tried this workaround:
OneWayToSource Binding seems broken in .NET 4.0
but it doesnt work either (value is always NaN).
I cant bind to ActualWidth/ActualHeight because they are read only (why can't I bind OnwayToSource on a readonly property!!)
What alternatives do I have? Do I have to derive Fish from DependancyObject and make my properties DPs?
XAML:
<DataTemplate DataType="{x:Type p:Fish}">
<Border BorderBrush="Black" BorderThickness="2" >
<TextBlock FontSize="14" TextAlignment="Center" VerticalAlignment="Center"
Width="{Binding Path=width, Mode=OneWayToSource}"
Height="{Binding Path=height, Mode=OneWayToSource}" ...
Code:
class Fish {
public double width { get; set; } // From DataTemplate TextBlock.Width.
public double height { get; set; } // From DataTemplate TextBlock.Height
}
...
double rendered_width = my_fish.width; // Use the rendered width!
I've finally realized what you're trying to do, and you're right that it should work. WPF, however, disagrees. I see that it's a problem that others have had before, but that is apparently by design. You can't set up a binding on a read only property, even if you're just wanting to bind OneWayToSource.
Here is a question with the same problem: OneWayToSource binding from readonly property in XAML Their workaround was to put a container (which has read/write width/height) around the xaml element and set up the binding on that container. This might work for you.
There is an unresolved issue related to this on Microsoft Connect where it is claimed to be behaviour by design: http://connect.microsoft.com/VisualStudio/feedback/details/540833/onewaytosource-binding-from-a-readonly-dependency-property. Someone claims a workaround in the related thread which uses a converter. You can try it, but I'm not sure it'll work in your case, as their binding was to a custom control, not a built in framework element.
Even Better
In This Solution, Boogaart came up with an implementation defining a new attached property (Similar to DockPanel.Dock="Top") which allows any element to provide its width and height for observation:
<TextBlock ...
SizeObserver.Observe="True"
SizeObserver.ObservedWidth="{Binding Width, Mode=OneWayToSource}"
SizeObserver.ObservedHeight="{Binding Height, Mode=OneWayToSource}"
Try it on and see if it fits.
If you consume these properties after some sort of action i.e. a button press or click on a hyperlink, then you can pass in the the ActualWidth and Height via a CommandParameter of a command. Otherwise I would suggest using triggers such as the ones available here:
http://expressionblend.codeplex.com/wikipage?title=Behaviors%20and%20Effects&referringTitle=Documentation
I agree that it appears counter intuitive that OneWayToSource bindings don't work on read only dependency properties.
Try binding OneWay. I think OneWayToSource is means wants to write to the source.
http://msdn.microsoft.com/en-us/library/system.windows.data.bindingmode.aspx
I did a test and sure enough Width = NaN until width is Assigned (set). I understand this is not the behavior you want. Try this. Where the Width is assigned it is reported (as 200). Where the Width is not assigned it is reported as NaN. But ActualWidth IS correct. ActualWidth is there but clearly the way you are trying to get it is not working.
<StackPanel Orientation="Vertical">
<Border BorderThickness="1" BorderBrush="Red">
<TextBlock Name="tbwidthA" Text="{Binding Path=Howdy}" HorizontalAlignment="Left" Width="200"/>
</Border>
<TextBlock Name="tbwidthAw" Text="{Binding ElementName=tbwidthA, Path=Width}" HorizontalAlignment="Left"/>
<TextBlock Name="tbwidthAaw" Text="{Binding ElementName=tbwidthA, Path=ActualWidth}" HorizontalAlignment="Left" />
<Border BorderThickness="1" BorderBrush="Red">
<TextBlock Name="tbwidthB" Text="{Binding Path=Howdy}" HorizontalAlignment="Left" />
</Border>
<TextBlock Name="tbwidthBw" Text="{Binding ElementName=tbwidthB, Path=Width}" HorizontalAlignment="Left" />
<TextBlock Name="tbwidthAbw" Text="{Binding ElementName=tbwidthB, Path=ActualWidth}" HorizontalAlignment="Left" />
<Button Content="TBwidth" Click="Button_Click_1" Width="60" HorizontalAlignment="Left" />
</StackPanel>
What is interesting is the Button does report the correct ActualWidth but Width is NaN.
Debug.WriteLine(tbwidthB.Width.ToString());
Debug.WriteLine(tbwidthB.ActualWidth.ToString());

wpf binding contextmenu

in my main view, I have a slider that can be used to scale the application.
<Slider x:Name="zoomSlider" VerticalAlignment="Center" Value="1" IsSnapToTickEnabled="True" TickFrequency="0.2" TickPlacement="Both" Minimum="0.5" Maximum="3" SmallChange="0.5" LargeChange="0.5" Width="100" />
and every control is scale-transformed accordingly:
<Controls:AutoHidePanel AutoHide="False" AutoFade="True" Height="50" Orientation="Horizontal">
<Controls:AutoHidePanel.LayoutTransform>
<ScaleTransform
ScaleX="{Binding Value, ElementName=zoomSlider}"
ScaleY="{Binding Value, ElementName=zoomSlider}"/>
</Controls:AutoHidePanel.LayoutTransform>
<MenuControl />
</Controls:AutoHidePanel>
This works fine: like this every control in my windows scales fine.
Now, the MenuControl is a view that has a splitbutton, and this splitbutton uses a context menu to display sub items. The button itself scales too, but the context menu does not scale.
How can I make sure that this context menu scales together with its button control?
Meanwhile I found a solution. I just set the data context of the context menu to its parent data context like:
<ContextMenu DataContext="{Binding RelativeSource={RelativeSource Mode=Self}, Path=PlacementTarget.DataContext}">

Resources