简体   繁体   中英

WPF Binding to ViewModel from separate

I am trying to create a Binding between my ViewModel and a ControlTemplate for a button, which is in a separate file that my View calls.

So far none of the standard methods have worked, and I am unsure how to tell the ControlTemplate button, which can be called from any View (and in fact I use in 2 views) to use the ViewModel attached to the View that calls it. Been searching for hours without a solution (neither an explanation nor example to extrapolate from). I may not be wording this correctly. I am using Caliburn Micro for MVVM.

ShellViewModel contains the following, which is set when my ShellView/ViewModel activates a View/ViewModel (Shell stays open, others exist inside of it when called).

public void LoadBuy()
    {
        ButtonBkgdBuy = "Blue";
        ActivateItem(BuyViewModel);
    }

private string _buttonBkgdBuy = "Green";
public string ButtonBkgdBuy
{
    get { return _buttonBkgdBuy; }
    set 
    { 
        _buttonBkgdBuy = value;
        NotifyOfPropertyChange(() => ButtonBkgdBuy);
    }
}

Clicking my button in the ShellView correct updates the ButtonBkgdBuy and activates my BuyViewModel. The button itself does not change it's color, nor have correct original color set as default in cs. Here is the button in ShellView:

<StackPanel>
    <Button Template="{DynamicResource BlackButton}" x:Name="LoadBuy"  Width="238" Margin="15,0,0,0"  FontSize="24" Height="40" Content="Browse Our Selection"/>
</StackPanel>

Template is in separate file, and introduced in App.xaml:

<Application x:Class="Retail_Kiosk.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:local="clr-namespace:Retail_Kiosk">
    <Application.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary>
                    <local:Bootstrapper x:Key="Bootstrapper" />
                    <Brush x:Key="BorderMain">#700000</Brush>
                    <Brush x:Key="BorderAccent">#7c4599</Brush>
                </ResourceDictionary>
                <ResourceDictionary Source="Templates\ButtonBlack.xaml"/>
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Application.Resources>
</Application>

Finally, a full version of the button's file to avoid missing something. The line in question I have added comments before and after

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <ControlTemplate TargetType="{x:Type Button}" x:Key="BlackButton">
        <Button Height="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=ActualHeight}"
                BorderBrush="{x:Null}" BorderThickness="0"
                Content="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Content}"
                >
            <Button.Effect>
                <DropShadowEffect BlurRadius="12" Color="Gray" Direction="270" Opacity=".8" ShadowDepth="3" />
            </Button.Effect>

            <Button.Template>
                <ControlTemplate TargetType="Button">
                    <Grid Width="{Binding RelativeSource={RelativeSource AncestorType=Button}, Path=ActualWidth}"
                          Height="{Binding RelativeSource={RelativeSource AncestorType=Button}, Path=ActualHeight}">
                        <Border x:Name="MainBorder" CornerRadius="3" Grid.ColumnSpan="2" Margin="0,0,4,4" BorderBrush="Black" BorderThickness="1">
                            <Border.Background>
                                <LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">
                                    <GradientStop Color="#FF5E5E5E" Offset="0" />
<!-- BEGIN: This is the Gradient that should be supplied a color, I know Binding isn't a full option, it's just my resting default. -->
<!-- If I add a color directly, the button has the color.  Code is correct.  If I try any of my binding attempts, binding fails and no color.-->
                                    <GradientStop Color="{Binding}" Offset="1" />
<!-- END -->
                                </LinearGradientBrush>
                            </Border.Background>
                            <Grid >
                                <Grid.ColumnDefinitions>
                                    <ColumnDefinition Width="*"/>
                                </Grid.ColumnDefinitions>

                                <Border CornerRadius="2" Margin="0" BorderBrush="LightGray" BorderThickness="0,1,0,0" Grid.ColumnSpan="2" Grid.RowSpan="2" />

                                <Grid Grid.Column="1" HorizontalAlignment="Left" VerticalAlignment="Center">
                                    <Grid.RowDefinitions>
                                        <RowDefinition Height="Auto" />
                                    </Grid.RowDefinitions>

                                    <TextBlock x:Name="Title" Text="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Content, FallbackValue='Button'}" 
                                                Grid.Column="1" Grid.Row="0" FontFamily="Calibri" FontWeight="Bold" 
                                                FontSize="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=FontSize}" 
                                                Foreground="White" Margin="10,0,0,0" Padding="0,0,0,0"/>
                                </Grid>
                            </Grid>
                        </Border>
                    </Grid>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsMouseOver" Value="True">
                            <Setter TargetName="MainBorder" Property="Background">
                                <Setter.Value>
                                    <LinearGradientBrush>
                                        <GradientStop Color="#000000" Offset="0" />
                                        <GradientStop Color="Aqua" Offset="1" />

                                    </LinearGradientBrush>
                                </Setter.Value>
                            </Setter>
                        </Trigger>
                        <Trigger Property="IsPressed" Value="True">
                            <Setter TargetName="MainBorder" Property="Background">
                                <Setter.Value>
                                    <LinearGradientBrush>
                                            <GradientStop Color="#000000" Offset="0" />
                                            <GradientStop Color="#7f10b3" Offset="1" />
                                    </LinearGradientBrush>
                                </Setter.Value>
                            </Setter>
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Button.Template>
        </Button>
    </ControlTemplate>
</ResourceDictionary>

Thank you for any help. I have never tried a binding like this, and while I assume possible, am not sure what this would be called. I'm happy to read up on it, if only I knew what to search.

Binding directly to ButtonBkgdBu should work provided that the Button to which the template is currently applied to has a DataContext with a public ButtonBkgdBuy property that returns a Color :

<GradientStop Color="{Binding ButtonBkgdBuy}" Offset="1" />

If you want to be able to use the same template for different data contexts, you should either create an attached property and bind to this one or use the Tag property or any other property of the Button itself:

<GradientStop Color="{Binding Tag, RelativeSource={RelativeSource AncestorType=Button}}" Offset="1" />

You can then set the property that you bind to in the template on each Button instance:

<StackPanel>
    <Button Template="{DynamicResource BlackButton}"
            Tag="Green"
            x:Name="LoadBuy"  Width="238" Margin="15,0,0,0"  FontSize="24" Height="40" Content="Browse Our Selection"/>
</StackPanel>

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