简体   繁体   中英

Conditional in XAML file?

I have the following XAML file:

<MediaElement Name="mediaElementOne"
              LoadedBehavior="Manual"
              Stretch="UniformToFill"
              ScrubbingEnabled="True"
              MediaOpened="Media_Success"
              MediaFailed="Media_Failure"/>

The MediaOpened property currently calls the "Media_Success" when the media loaded successfully.

My issue is with MediaFailed , because I only want MediaFailed to fire on a boolean, meaning I need this to be conditional based on a boolean in my .cs file for the aforementioned XAML file.

How do I write a conditional in a XAML file? Or how would I be able to do this on the .cs file.

Right now as soon as .net believes the media failed it fires the Media_Failure function. I don't want it to fire the Media_Failure function when a specific boolean is set to false and for reasons far outside the scope of this question I can't handle the condition inside of the Media_Failure function.

Additional info: Here is the method it fires on the .cs file:

private void Media_Failure(object sender, ExceptionRoutedEventArgs e){...}

You can use triggers.

This code is in reference to winrt xaml. The same can you do in WPF:

<Interactivity:Interaction.Behaviors>
    <Core:DataTriggerBehavior Binding="{Binding IsFailed}" Value="True">
      <Core:CallMethodAction MethodName="MediaFailed"/>
    </Core:DataTriggerBehavior>
</Interactivity:Interaction.Behaviors>

This will go with your media element.

So, if your bool is true it will call a method.

A pattern like this comes to mind where you set or clear the MediaFailed event handler based on the boolean, which you make a property with a getter/setter.

private bool _isMediaFailureEnabled;
public bool isMediaFailureEnabled
{
    get
    {
        return _isMediaFailureEnabled;
    }

    set
    {
        if (_isMediaFailureEnabled != value)
        {
            _isMediaFailureEnabled = value;
            if (_isMediaFailureEnabled)
            {
                mediaElementOne.MediaFailed += MediaElementOne_MediaFailed;
            }
            else
            {
                mediaElementOne.MediaFailed -= MediaElementOne_MediaFailed;
                // OR
                // mediaElementOne.MediaFailed = null;
            }
        }
    }
}

You will have to inspire from this pattern and adapt to your code, but this should accomplish what you want.

Edit:

Thought about this more for some reason and arrived at an alternative which is very similar to what Maurice came up with, by using a level of abstraction to solve the problem.

Define a wrapper or the failed event:

MediaFailed="Media_Failure_Wrapper"

Always let this be called, and only call your original event handler when your boolean is true:

private void Media_Failure_Wrapper(object sender, ExceptionRoutedEventArgs e)
{
    if (_isMediaFailureEnabled)
    {
        return Media_Failure(sender, e);
    }
    else
    {
        e.Handled = true;
        return;
    }
}

Here is a way to do it( without any extra lib like interactivity etc).

Create a helper class: (which gives you flexibility to write down logic for events and/or behaviors and/or triggers and/or command bindings and/or a middle layer for event handling).

public class RoutedEventTrigger : FrameworkElement
{       
    RoutedEvent _routedEvent;
    public RoutedEvent RoutedEvent
    {
        get { return _routedEvent; }
        set { _routedEvent = value; }
    }

    private Action<object, RoutedEventArgs> handler;
    public Action<object, RoutedEventArgs> Handler
    {
        get { return handler; }
        set { handler = value; }
    }

    public static DataTemplate GetTemplate(DependencyObject obj)
    {
        return (DataTemplate)obj.GetValue(TemplateProperty);
    }

    public static void SetTemplate(DependencyObject obj, DataTemplate value)
    {
        obj.SetValue(TemplateProperty, value);
    }

    public static readonly DependencyProperty TemplateProperty =
        DependencyProperty.RegisterAttached("Template",
        typeof(DataTemplate),
        typeof(RoutedEventTrigger),
        new PropertyMetadata(default(DataTemplate), OnTemplateChanged));

    private static void OnTemplateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        DataTemplate dt = (DataTemplate)e.NewValue;
        if (dt != null)
        {
            dt.Seal();
            RoutedEventTrigger ih = (RoutedEventTrigger)dt.LoadContent();
            (d as FrameworkElement).AddHandler(ih.RoutedEvent, new RoutedEventHandler(ih.OnRoutedEvent));                
        }
    }

    void OnRoutedEvent(object sender, RoutedEventArgs args)
    {
        Handler.Invoke(sender, args);
    }
    
} 

XAMl: (Just set the helper class properties from XAML and this will work with any element.)

<Button Height="100" Width="200" Content="Click" Name="mybutton" >
    <Button.Style>
        <Style TargetType="{x:Type Button}">
            <Style.Triggers>
                <DataTrigger Binding="{Binding IsEventAttached}" Value="true">
                    <Setter  Property="local:RoutedEventTrigger.Template">
                        <Setter.Value>
                            <DataTemplate>
                                <local:RoutedEventTrigger RoutedEvent="Button.Click" Handler="MySlider_ValueChanged" />
                            </DataTemplate>
                        </Setter.Value>
                    </Setter>
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </Button.Style>
</Button>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM