0

アプリを開発していると、「タイル」コントロールを頻繁に再作成していることに気付きました。したがって、私は現在、再利用のためにそれをユーザーコントロールに移動しようとしています。ただし、現在、以前は機能していたバインディングを受け入れていません。したがって、たとえば:

<Canvas Height="73" Width="73" VerticalAlignment="Top" Margin="10,10,8,0">
    <Rectangle Height="73" Width="73" VerticalAlignment="Top" Fill="{Binding Path=Active, Converter={StaticResource IconBackground}}" />
    <Image Height="61" Width="61" VerticalAlignment="Center" HorizontalAlignment="Center" Margin="6"  Source="{Binding Tone.Image}" />
</Canvas>

バインディングで正常に動作し、

<views:Tile Height="73" Width="73" Background="{Binding Path=Active, Converter={StaticResource IconBackground}, Mode=OneWay}" Icon="{Binding Path=Tone.Image, Mode=OneTime}" />

「パラメータが正しくありません」というエラーが発生します。

TileUserControlのコードは次のとおりです。

Tile.xaml

<UserControl x:Class="RSS_Alarm.Views.Tile"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    FontFamily="{StaticResource PhoneFontFamilyNormal}"
    FontSize="{StaticResource PhoneFontSizeNormal}"
    Foreground="{StaticResource PhoneForegroundBrush}"
    d:DesignHeight="100" d:DesignWidth="100">

    <Grid x:Name="LayoutRoot">
        <Canvas Height="100" Width="100" Margin="0,0,0,0">
            <Rectangle Name="rectBackground" Height="100" Width="100" />
            <Image Name="imgIcon" Height="80" Width="80" VerticalAlignment="Center" HorizontalAlignment="Center" Canvas.Left="10" Canvas.Top="10" />
        </Canvas>
    </Grid>
</UserControl>

Tile.xaml.cs

namespace RSS_Alarm.Views
{
    public partial class Tile : UserControl
    {
        public Tile()
        {
            InitializeComponent();
        }

        public String Icon
        {
            get
            {
                return imgIcon.Source.ToString();
            }

            set
            {
                BitmapImage alarmIcon = new BitmapImage();
                alarmIcon.UriSource = new Uri(value, UriKind.Relative);
                imgIcon.Source = alarmIcon;
            }

        }

        new public Brush Background
        {
            get
            {
                return rectBackground.Fill;
            }

            set
            {
                rectBackground.Fill = value;
            }
        }

        new public double Height
        {
            get
            {
                return rectBackground.Height;
            }

            set
            {
                rectBackground.Height = value;
                imgIcon.Height = value * 0.8;
            }
        }

        new public double Width
        {
            get
            {
                return rectBackground.Width;
            }

            set
            {
                rectBackground.Width = value;
                imgIcon.Width = value * 0.8;
            }
        }
    }
}

さらにソースが必要な場合は、お知らせください。投稿します。Height固定値を使用しても問題はありませんが(赤Widthに設定すると問題ありません)、バインディング値に変更すると例外がスローされます。Background


編集1

更新されたコードは次のとおりです。

Tile.xaml.cs

#region Background
        public static readonly DependencyProperty RectBackgroundProperty =
           DependencyProperty.Register(
               "RectBackground",
               typeof(SolidColorBrush),
               typeof(Tile),
               new PropertyMetadata(new SolidColorBrush(Colors.Green), new PropertyChangedCallback(OnBackgroundChanged))
           );

        public static void OnBackgroundChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            Debug.WriteLine("Filling background");
            ((Tile)d).rectBackground.Fill = (Brush)e.NewValue;
        }

        new public SolidColorBrush Background
        {
            get { return (SolidColorBrush)GetValue(RectBackgroundProperty); }
            set { 
                Debug.WriteLine("Setting colour"); 
                SetValue(RectBackgroundProperty, value); 
            }
        }
#endregion

MainMenuControl.xaml.cs

// Class to determine the background colour of the icon (active/inactive)
public class IconBackground : System.Windows.Data.IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        bool b = (bool)value;

        Debug.WriteLine("Converting colour. Value is " + b.ToString());

        if (b)
        {
            return (Brush)App.Current.Resources["PhoneAccentBrush"];
        }
        else
        {
            return new SolidColorBrush(Colors.DarkGray);
        }
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        SolidColorBrush brush = (SolidColorBrush)value;

        if (brush.Color.Equals(Colors.DarkGray))
        {
            return false;
        }
        else
        {
            return true;
        }
    }

}

また、2つの方法を並べて比較しています。左側のタイルは、バインディングが完全に機能する定義済みのキャンバスであり、右側のタイルは、定義された色(この場合は青)でのみ機能するTileUserControlです。

スクリーンショット

4

1 に答える 1

2

XAML でバインドできるようにするには、プロパティを作成するだけでは不十分です。DependencyPropertyを作成する必要があります。

Backgroundバインディングが機能する理由は、UserControlそれ自体がこのプロパティを持っているためです。プロパティ セッターにブレークポイントを設定するBackgroundと、それが呼び出されないことがわかります。

DependencyPropertyこれはあなたの例ですBackground(テストされていません)

#region Background
        public const string BackgroundPropertyName = "Background";
        public new Brush Background
        {
            get { return (Background)GetValue (BackgroundProperty); }
            set { SetValue (Background, value); }
        }
        public static new readonly DependencyProperty BackgroundProperty = DependencyProperty.Register (
            BackgroundPropertyName,
            typeof (Brush),
            typeof (Tile),
            new PropertyMetadata (BackgroundChanged));

        static void BackgroundChanged (DependencyObject d, DependencyPropertyChangedEventArgs e)
        {                
            ((Tile) d).rectBackground = (Brush)e.NewValue;    
        }
    #endregion
于 2012-05-03T18:01:29.757 に答える