Silverlight: Как мне динамически обновлять свойства в соответствии с текущим классом настроек? - PullRequest
3 голосов
/ 19 февраля 2011

Ниже приведен полный код для примера. У меня есть пользовательский элемент управления под названием ColorPicker, который содержит 3 кнопки, каждая из которых отображает цвет. При нажатии кнопки устанавливается свойство Color в классе CurrentSettings. Я хочу, чтобы цвет прямоугольника на главной странице изменился в соответствии с новым CurrentSettings.Color и цветом прямоугольников (добавленных в коде сзади) в списке во втором пользовательском элементе управления, чтобы также изменить цвет в соответствии с новый CurrentSettings.Color.

Я пытался выполнить это безуспешно, используя Dependency Properties и INotifyPropertyChanged, и теперь решил начать заново с чистого листа.

// Текущий класс Sttings:

public static class CurrentSettings
{
    public static Color Color { get; set; }
}

// MainPage XAML

<Grid x:Name="LayoutRoot">
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="33*"/>
        <ColumnDefinition Width="33*"/>
        <ColumnDefinition Width="33*"/>
    </Grid.ColumnDefinitions>
    <local:ColorPicker/>
    <Rectangle Grid.Column="1" Name="rec" Width="160" Height="80" Fill="Yellow"/>
    <local:PenSelector Grid.Column="2"/>
</Grid>

// Элемент управления ColorPicker XAML:

<StackPanel x:Name="LayoutRoot" Orientation="Horizontal">
    <Button x:Name="Red" Width="40" Height="40" Click="Red_Click">
        <Button.Content>
            <Rectangle Width="30" Height="30" Fill="Red"/>
        </Button.Content>
    </Button>
    <Button x:Name="Green" Width="40" Height="40" Click="Green_Click">
        <Button.Content>
            <Rectangle Width="30" Height="30" Fill="Green"/>
        </Button.Content>
    </Button>
    <Button x:Name="Blue" Width="40" Height="40" Click="Blue_Click">
        <Button.Content>
            <Rectangle Width="30" Height="30" Fill="Blue"/>
        </Button.Content>
    </Button>
</StackPanel>

// Код управления пользователя ColorPicker:

public partial class ColorPicker : UserControl
{
    public ColorPicker()
    {
        InitializeComponent();
    }

    private void Red_Click(object sender, RoutedEventArgs e)
    {
        CurrentSettings.Color = Colors.Red;
    }

    private void Green_Click(object sender, RoutedEventArgs e)
    {
        CurrentSettings.Color = Colors.Green;
    }

    private void Blue_Click(object sender, RoutedEventArgs e)
    {
        CurrentSettings.Color = Colors.Blue;
    }
}

// Пользовательский элемент управления селектором пера XAML:

<ListBox x:Name="LayoutRoot"/>

// Пользовательский элемент управления селектором пера XAML-код:

public partial class PenSelector : UserControl
{
    public PenSelector()
    {
        InitializeComponent();

        LayoutRoot.Items.Add(new Rectangle() { Width = 160, Height = 80, Fill = new SolidColorBrush(Colors.Yellow) });
        LayoutRoot.Items.Add(new Rectangle() { Width = 160, Height = 80, Fill = new SolidColorBrush(Colors.Yellow) });
    }
}

Ответы [ 2 ]

3 голосов
/ 19 февраля 2011

Вы были на правильном пути с INotifyPropertyChanged. Начните с класса параметров, но задайте свойство Color для свойства экземпляра класса, который реализует INotifyPropertyChanged.

 public class CurrentSettings : INotifyPropertyChanged
 {
     private Color _Color;
     public Color Color
     {
        get { return _Color; }
        set { _Color = value; NotifyPropertyChanged("Color"); }
     }
     private void NotifyPropertyChanged(string name)
     {
         if (PropertyChanged != null)
             PropertyChanged(this, new PropertyChangedEventArgs(name);
     }
     public event PropertyChangedEventHandler PropertyChanged;
 }

Теперь поместите экземпляр этого в Ресурсы ваш App.Xaml: -

 <Application.Resources>
     <local:CurrentSettings x:Key="CurrentSettings" />
 </Application.Resources>

Теперь добавьте частную собственность CurrentSettings в палитру цветов: -

private CurrentSettings CurrentSettings
{
   get
   {
        return (CurrentSettings)Application.Current.Resources["CurrentSettings"];
   }
}

Наконец, используйте привязку к свойству прямоугольника Fill, например: -

<Rectangle Grid.Column="1" Name="rec">
    <Rectangle.Fill>
         <SolidColorBrush Color="{Binding Color, Source={StaticResource CurrentSettings}}"/>
    </Rectangle.Fill>
</Rectangle>
1 голос
/ 19 февраля 2011

У вас здесь довольно много движущихся частей - пользовательский контроль colorPicker, который изменяет POCO в главной форме, которая, в свою очередь, обновляет элементы, добавленные в другой пользовательский контроль PenSelector - если я вас правильно понимаю. Если вы добавите DP в ваши usercontrols и добавите INotifyPropertyChanged к своему POCO, то, в свою очередь, привяжете DP к общедоступному свойству POCO, вы должны иметь возможность взаимодействия, которое вы хотите, с некоторой развязкой между частями:

Поко:

public class CurrentSelected:INotifyPropertyChanged
{

    #region INotifyPropertyChanged Members

    public event PropertyChangedEventHandler PropertyChanged;

    protected void Notify(string propName)
    {
        if (this.PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propName));
        }
    }
    #endregion


    private SolidColorBrush color;

    public SolidColorBrush Color
    {
        get { return color; }
        set { 
            if (this.color==value) return;
            this.color = value;
            Notify("Color");
        }
    }

    public CurrentSelected() { 
        this.color = new  SolidColorBrush(Colors.Orange);
    }

}

Главное окно:

<Grid x:Name="LayoutRoot" Background="White">
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="33*"/>
        <ColumnDefinition Width="33*"/>
        <ColumnDefinition Width="33*"/>
    </Grid.ColumnDefinitions>
    <local:ColorPicker CurrentColor="{Binding Path=Color, Mode=TwoWay}" Grid.Column="0"/>
    <Rectangle Fill="{Binding Path=Color}" Grid.Column="1" Width="160" Height="80" />
    <local:PenSelector ColorSelected="{Binding Path=Color, Mode=TwoWay}" Grid.Column="2"/>
</Grid>

Код:

CurrentSelected Settings = new CurrentSelected();

    public MainPage()
    {
        InitializeComponent();
        this.DataContext = this.Settings;
    }

Элементы управления пользователя - ColorPicker

<StackPanel x:Name="LayoutRoot" Orientation="Horizontal">
    <Button Click="Button_Click">
        <Button.Content>
            <Rectangle Fill="Red"/>
        </Button.Content>
    </Button>

    <Button Click="Button_Click">
        <Button.Content>
            <Rectangle Fill="Green"/>
        </Button.Content>
    </Button>
    <Button Click="Button_Click">
        <Button.Content>
            <Rectangle Fill="Blue" />
        </Button.Content>
    </Button>
</StackPanel>

Его код:

public static readonly DependencyProperty CurrentColorProperty=
        DependencyProperty.Register("CurrentColor",
            typeof(SolidColorBrush), typeof(ColorPicker),
            new PropertyMetadata(new SolidColorBrush(Colors.Gray)));

    public SolidColorBrush CurrentColor
    {
        get
        {
            return (SolidColorBrush)GetValue(CurrentColorProperty);
        }
        private set
        {
            SetValue(CurrentColorProperty, value);
        }
    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        Button b = (Button)sender;
        Shape r = (b.Content) as Shape;
        SolidColorBrush sb = new SolidColorBrush(Colors.Yellow);
        sb = (SolidColorBrush)r.Fill;
        this.CurrentColor = sb;
    }

Пользовательский контроль PenSelector

xaml, как у вас, просто ListBox, вся работа в коде

public static readonly DependencyProperty ColorSelectedProperty =
        DependencyProperty.Register(
            "ColorSelected", 
            typeof(SolidColorBrush),
            typeof(PenSelector), 
            new PropertyMetadata(new SolidColorBrush(Colors.Yellow)));

    public SolidColorBrush ColorSelected
    {
        get
        {
            return (SolidColorBrush)GetValue(ColorSelectedProperty);
        }
        set
        {
            SetValue(ColorSelectedProperty, value);
        }
    }

    public PenSelector()
    {
        InitializeComponent();

        LayoutRoot.Items.Add(addRectangle());
        LayoutRoot.Items.Add(addRectangle());
    }

    private Rectangle addRectangle()
    {
        Rectangle r = new Rectangle() { Width = 160, Height = 80 };
        Binding b = new Binding();
        b.Source=this;
        b.Path=new PropertyPath("ColorSelected");
        b.Mode=BindingMode.OneWay;
        r.SetBinding(Rectangle.FillProperty, b);
        return r;
    }

Я определил POCO и DP как SolidColorBrushes, хотя вы, вероятно, захотите использовать Color и конвертер для преобразования в Brush. Настройки экземпляра класса CurrentSelected назначаются текстовому тексту mainWindows. На ColorPicker я только что поместил код в один обработчик нажатия кнопки, и он получает цвет, основанный на цвете заливки, указанном в xaml. Это обновляет текущее цветное DP на сборщике. PenSelector устанавливает прямоугольники с привязками к своему собственному DP, после чего остается только настроить привязку данных в MainWindow для свойства Color, предоставляемого CurrentSelected. DP определяют значения по умолчанию. Есть и другие способы сделать все это, но это зависит от ваших требований (как всегда)!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...