如何使bool类型的依赖属性成为双向绑定

时间:2015-04-12 06:37:53

标签: wpf xaml

任何人都可以帮我解决这个问题,因为我在博客上读到了如何做到这一点 Walkthrough: Two-way binding inside a XAML User Control 但我现在不知道如何用bool值来做到这一点

    public bool IsSelected
    {
        get { return (bool)GetValue(IsSelectedProperty); }
        set { SetValueIsSelected(IsSelectedProperty, value); }
    }

    private void SetValueIsSelected(DependencyProperty property, object value,
        [System.Runtime.CompilerServices.CallerMemberName] bool s = null)
    {
        SetValue(property, value);
        if (PropertyChanged != null)
        {
            string sender = s.ToString();
            PropertyChanged(this, new PropertyChangedEventArgs(sender));
        }
    }
    // Using a DependencyProperty as the backing store for IsSelected.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty IsSelectedProperty =
        DependencyProperty.Register("IsSelected", typeof(bool), typeof(CustomPolygon), new PropertyMetadata(0));

所以这是错误的@Clemens 在这里了解更多关于我的应用程序的更多信息

在我的MainWindow中,我使用两个ComboBox来填充我的数据并绑定到公共ObservableCollection DataPlannen

我在MainWindow背后的代码:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
    }

    private ObservableCollection<Plan> dataPlannen;
    public ObservableCollection<Plan> DataPlannen
    {
        get { return dataPlannen; }
        set
        {
            if (value != dataPlannen)
            {
                dataPlannen = value;
            }
        }
    }

    //non relevant code deleted


    //get database data for ComboBoxes
    private void btnGetPlanData_Click(object sender, RoutedEventArgs e)
    {
        try
        {
            this.Cursor = Cursors.Wait;
            DataPlannen = new PlanCanvasModel().PlanHotspotsHardwares;             
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.ToString();
        }
        finally
        {
            this.Cursor = Cursors.Arrow;
        }
    }

    private void cmbHotspot_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
       if (cmbHotspot.SelectedIndex != -1)
       {
         foreach (Hotspot hotspot in cmbHotspot.ItemsSource)
         {
            if (hotspot == (Hotspot)cmbHotspot.SelectedItem)
            {
                 hotspot.IsSelected = true;

             else
             {
                 hotspot.IsSelected = false;
              }
          }
    }
}

My MainWindow XAML:

    <Grid Background="LightGray">
    <DockPanel Name="TestCanvas" LastChildFill="True">
        <Grid x:Name="Sidebar" DockPanel.Dock="Right" Width="200">
            <StackPanel Margin="0,10,10,0">
                <ScrollViewer Height="112" VerticalScrollBarVisibility="Auto">
                    <StackPanel>
                        <StackPanel Orientation="Horizontal" Margin="0,0,0,5">
                            <Button x:Name="btnGetPlanData" Width="30" Height="30" HorizontalAlignment="Left" Margin="5,0" Click="btnGetPlanData_Click">
                                <Image Source="Images/database38.png" Stretch="Uniform"></Image>
                                <Button.ToolTip>Laad plannen in</Button.ToolTip>
                            </Button>

                        </StackPanel>
                        <Grid>
                            <ComboBox x:Name="cmbPlannen" Width="180"
                                      ItemsSource="{Binding ElementName=myWindow,Path=DataPlannen}" 
                                      DisplayMemberPath="{Binding Plan_naam}"
                                      SelectedValuePath="{Binding Plan_Id}"
                                      SelectionChanged="cmbPlannen_SelectionChanged" IsEditable="True">
                                <ComboBox.ToolTip>
                                    <ToolTip>Zoek op text of selecteer</ToolTip>
                                </ComboBox.ToolTip>
                            </ComboBox>

                        </Grid>
                    </StackPanel>
                </ScrollViewer>
                <Grid>
                    <ComboBox Margin="5" SnapsToDevicePixels="True" ItemsSource="{Binding ElementName=cmbPlannen,Path=SelectedItem.Hotspots,Mode=TwoWay}"
                              x:Name="cmbHotspot" SelectedIndex="0"
                              DisplayMemberPath="{Binding Hotspot_naam}"
                              SelectedValuePath="{Binding Hotspot_Id}"
                              SelectedItem="{Binding SelectedItem}"
                              SelectionChanged="cmbHotspot_SelectionChanged"  IsEditable="True">
                        <ComboBox.ItemContainerStyle>
                            <Style>
                                <Setter Property="Control.Padding" Value="0"></Setter>
                                <Style.Triggers>
                                    <Trigger Property="ComboBoxItem.IsSelected" Value="True">
                                        <Setter Property="ComboBoxItem.Background" Value="LightGray" />
                                    </Trigger>
                                    <Trigger Property="ComboBoxItem.IsHighlighted" Value="True">
                                        <Setter Property="ComboBoxItem.Background" Value="White" />
                                    </Trigger>
                                </Style.Triggers>
                            </Style>
                        </ComboBox.ItemContainerStyle>
                        <ComboBox.ToolTip>
                            <ToolTip>Zoek op text of selecteer</ToolTip>
                        </ComboBox.ToolTip>
                    </ComboBox>
                </Grid>

            </StackPanel>
        </Grid>

        <Grid x:Name="MainContainer" ClipToBounds="True"
                       >
            <Viewbox>
                <ItemsControl x:Name="drawingsheet" ItemsSource="{Binding ElementName=cmbPlannen, Path=SelectedItem.Hotspots}"
                                Width="{StaticResource canvasWidth}"
                                Height="{StaticResource canvasHeight}"
                                MouseLeftButtonUp="drawingsheet_MouseLeftButtonUp"
                                MouseRightButtonDown="drawingsheet_MouseRightButtonDown"
                                MouseWheel="drawingsheet_MouseWheel"
                                MouseLeftButtonDown="drawingsheet_MouseLeftButtonDown"
                                MouseMove="drawingsheet_MouseMove"
                                Background="White"
                                >
                    <ItemsControl.ItemsPanel>
                        <ItemsPanelTemplate>
                            <Canvas Background="{Binding ElementName=cmbPlannen,Path=SelectedItem.Plan_image,Converter={StaticResource ResourceKey=bytesToBitmapImageConverter}}"
                                    Width="{StaticResource canvasWidth}" Height="{StaticResource canvasHeight}"  />
                        </ItemsPanelTemplate>
                    </ItemsControl.ItemsPanel>
                    <ItemsControl.ItemTemplate>
                        <DataTemplate>
                            <customPolygon:CustomPolygon x:Name="currentPolygon" PointsPolygon="{Binding Hotspot_points}"
                                                          IsSelected="{Binding IsSelected,Mode=TwoWay}"
                                                          HasChildren="{Binding HasChildren}"></customPolygon:CustomPolygon>
                        </DataTemplate>
                    </ItemsControl.ItemTemplate>
                    <ItemsControl.ItemContainerStyle>
                        <Style>
                            <Setter Property="Canvas.Top" Value="{Binding Path=Y}" />
                            <Setter Property="Canvas.Left" Value="{Binding Path=X}" />
                        </Style>
                    </ItemsControl.ItemContainerStyle>
                    <ItemsControl.RenderTransform>
                        <TransformGroup>
                            <ScaleTransform x:Name="scaleCanvas"></ScaleTransform>
                            <TranslateTransform x:Name="moveCanvas"></TranslateTransform>
                        </TransformGroup>
                    </ItemsControl.RenderTransform>
                </ItemsControl>
            </Viewbox>
        </Grid>

    </DockPanel>
</Grid>

我的UserControl CustomPolygon.Xaml:

<UserControl x:Class="testCanvas.Controls.DrawingControls.CustomPolygon"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
         xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" 
         mc:Ignorable="d"
         Name="userControl"
        >
<Polygon x:Name="polygon"
         Points="{Binding ElementName=userControl,Path=PointsSource}"
         StrokeThickness="0.5"
         Stroke="Black"
         Opacity="0.5"            
         MouseEnter="polygon_MouseEnter"
         MouseLeave="polygon_MouseLeave"
         MouseLeftButtonDown="polygon_MouseLeftButtonDown"/>
    </UserControl>

我的代码来自CustomPolygon

public partial class CustomPolygon : UserControl, INotifyPropertyChanged
{
    public CustomPolygon()
    {
        InitializeComponent();
    }

    #region Properties

    public bool IsSelected
    {
        get { return (bool)GetValue(IsSelectedProperty); }
        set
        {
            SetValue(IsSelectedProperty, value);
            if (IsSelected)
            {
                polygon.Stroke = Brushes.Red;
                polygon.StrokeThickness = 2;
            }
            else
            {
                polygon.Stroke = Brushes.Black;
                polygon.StrokeThickness = 0.5;
            }
        }
    }
    // Using a DependencyProperty as the backing store for IsSelected.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty IsSelectedProperty =
        DependencyProperty.Register("IsSelected", typeof(bool), typeof(CustomPolygon),
    new FrameworkPropertyMetadata(false, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));

    //points for polygon
    public PointCollection PointsPolygon
    {
        get { return (PointCollection)GetValue(PointsPolygonProperty); }
        set { SetValue(PointsPolygonProperty, value); }
    }
    // Using a DependencyProperty as the backing store for PointsPolygon.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty PointsPolygonProperty =
        DependencyProperty.Register("PointsPolygon", typeof(PointCollection), typeof(CustomPolygon),
          new FrameworkPropertyMetadata(false, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));



    public bool HasChildren
    {
        get { return (bool)GetValue(HasChildrenProperty); }
        set { SetValue(HasChildrenProperty, value); }
    }

    // Using a DependencyProperty as the backing store for HasChildren.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty HasChildrenProperty =
        DependencyProperty.Register("HasChildren", typeof(bool), typeof(CustomPolygon),
        new FrameworkPropertyMetadata(false, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));
    #endregion

    private void polygon_MouseEnter(object sender, MouseEventArgs e)
    {
        if (IsSelected != true)
        {
            polygon.Stroke = new SolidColorBrush((Color)ColorConverter.ConvertFromString(Properties.Settings.Default.HotspotHover));
            polygon.StrokeThickness = 1;
        }

    }

    private void polygon_MouseLeave(object sender, MouseEventArgs e)
    {
        if (IsSelected != true)
        {
            polygon.Stroke = Brushes.Black;
            polygon.StrokeThickness = 0.5;
        }
    }

    private void polygon_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
    {
        IsSelected = !IsSelected;
    }
    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void OnPropertyChanged(string propertyName)
    {
        if (this.PropertyChanged != null)
            this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
}

现在问题是如果我在cmbHotspot中更改我的选择,我的usercontrol中的属性没有变化,反之亦然

1 个答案:

答案 0 :(得分:2)

他们在这篇博客中所说的内容对于WPF来说是不正确的。这篇文章不是关于WPF,它在Windows运行时甚至不需要它。您绝对应该忽略有关在自定义控件的构造函数中设置DataContext的部分。

无论如何,您不能在依赖项属性的CLR包装器的setter中调用除SetValue以外的任何内容。有关详细信息,请参阅MSDN上的XAML Loading and Dependency Properties文章。

除了依赖属性不需要引发PropertyChanged事件之外,所以你的SetValueIsSelected属性无论如何都是多余的。

最后,您的属性元数据错误,因为0不是类型bool的有效默认值。

您的声明应如下所示:

public static readonly DependencyProperty IsSelectedProperty =
    DependencyProperty.Register(
        "IsSelected", typeof(bool), typeof(CustomPolygon));

public bool IsSelected
{
    get { return (bool)GetValue(IsSelectedProperty); }
    set { SetValue(IsSelectedProperty, value); }
}

除非您不想设置任何非标准属性元数据,否则无需指定PropertyMetadata方法的Register参数。

但是,如果您希望该属性默认绑定为双向,则必须按属性元数据设置相应的标志。

public static readonly DependencyProperty IsSelectedProperty =
    DependencyProperty.Register(
        "IsSelected", typeof(bool), typeof(CustomPolygon),
        new FrameworkPropertyMetadata(
            false, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault);