WPF C#
The below code correctly draws a ToggleButton, B10, which will blink when clicked from the user interface (the custom control RingButtons2) and correctly execute the associated relay command, NewRecordingCmd, in the AudioRecorder. If it is clicked again, it will correctly stop blinking. All is well.
How can the B10 ToggleButton's state be changed back to the unclicked-- non-blinking state from code in the AudioRecorder via the RingButtons2 control? To say this another way, how can I reset the B10 ToggleButton to its initial state from code in the AudioRecorder when there is an intermediary RingButtons2 control?
This does NOT work from the AudioRecorder:
NewRecordingCmd.Execute(false);
Thanks in advance for any help or suggestions.
The ToggleButton is basically defined within my custom control (Generic.xaml) as:
<Style x:Key="BaseButtonStyle" TargetType="{x:Type ToggleButton}">
<Setter Property="local:ButtonProperties.MyForegroundColor" Value="Blue"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ToggleButton}">
<Grid>
<Path x:Name="path1" Data="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=(local:ButtonProperties.Data)}"
Fill="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=(local:ButtonProperties.Fill)}"
Stroke="Black"/>
<ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" RecognizesAccessKey="True"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="true">
<Setter TargetName="path1" Property = "Opacity" Value="0.4"/>
</Trigger>
<Trigger Property="IsChecked" Value="true">
<Trigger.EnterActions>
<BeginStoryboard Storyboard="{StaticResource Blink_On}"/>
</Trigger.EnterActions>
<Trigger.ExitActions>
<BeginStoryboard Storyboard="{StaticResource Blink_Off}"/>
</Trigger.ExitActions>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Then, in OnApplyTemplate():
_B10 = GetTemplateChild("PART_Button10") as ToggleButton;
_B10.Command = B10Cmd;
where in the custom control, B10Cmd is:
public ICommand B10Cmd
{
get { return (ICommand)GetValue(B10CmdProperty); }
set { SetValue(B10CmdProperty, value); }
}
// Using a DependencyProperty as the backing store for B10Cmd. This enables animation, styling, binding, etc...
public static readonly DependencyProperty B10CmdProperty =
DependencyProperty.Register("B10Cmd", typeof(ICommand), typeof(RingButtons2), new UIPropertyMetadata(null));
The RingButtons2 cusom control is then used from the user interface Xaml as:
<w:RingButtons2
B10Cmd ="{Binding NewRecordingCmd, ElementName=AudioRecorder}"
/>
The NewRecordingCmd in the AudioRecorder (also a custom control) is defined as:
public RelayCommand<bool> NewRecordingCmd
{
get
{
if (_newRecordingCmd == null)
{
_newRecordingCmd = new RelayCommand<bool>(
(isChecked) =>
{
if (isChecked)
{
ActiveAudioFile = Path.Combine(Path.GetTempPath(), Guid.NewGuid() + ".wav");
AudioFileState = AudioFileStateEnum.New; // File has not been created yet.
FileLoaded = false;
}
}, (isChecked) => AudioRecorderState == AudioRecorderStateEnum.Monitoring);
}
return _newRecordingCmd;
}
}
It's not clear from you post how your ViewModel looks like, but in general if you use an MVVM pattern, in/from viemodel you can't coerce a view layer to do something(change the state of radio button) but only provide information and view(if it wants) can use this information(via binding), so to say allows to be impacted.
Command is an action, which being executed on some event, e.g. Click
, so you can't bind an action to the property which describes the state IsChecked
.
So to impact the view you need just to provide a property, say IsRecording
, in ViewModel, which you can/should bind to the IsChecked
propertie of the radio button PART_Button10
. Alternating a IsRecording
you will impact(set/reset a radio button) a view.
The binding to the IsRecording
you can do either in Xaml (there is no XAML definition for PART_Button10
in your post) or in code behind e.g. in OnApplyTemplate()
:
BindingOperations.SetBinding(_B10, RadioButton.IsCheckedProperty, new Binding("IsRecording"));
As I already said - the question is what the DataContext of all controls is.
I would eventually make in user control a dependency property not a command B10Cmd
, but a bool IsRecording
and bind it with the same bool property in viewmodel and do all stuff with recording in it's setter.