Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > WPF и Silverlight > Как использовать свойства UserControl?


Автор: dazy 3.4.2009, 12:34
Если я делаю контрол и наследую его от UsesrControl, то по умолчанию он имеет множество различных свойств.
Как ими пользоваться? Например как правильно воспользоваться свойством Foreground, чтобы не создавать свой аналог этого свойства?

Автор: Idsa 3.4.2009, 12:41
Ничего особенного в их использовании, на мой взгляд, нет. Возьмем вышеуказанное свойство Foreground. Идем в MSDN. Видим, что это Dependency property со следующими флагами: AffectsRender, SubPropertiesDoNotAffectRender, Inherits. Значит при выставлении Foreground у UserControl, Foreground дочерних контролов также поменяется (если не прописан явно).

Автор: dazy 3.4.2009, 13:01
А можно на примере?

Сделал кнопку как UserControl

Код

<UserControl
    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"
    x:Class="TryDP.SQ"
    d:DesignWidth="88" d:DesignHeight="48">

    <Grid x:Name="LayoutRoot">
        <Button Content="Button"/>
    </Grid>
</UserControl>

В самом коде ни чего не пишу.

На страничке пользуюсь этим контролом, выставляю свойства.  Но эффекта нет. Кнопка все равно дефолтная.
Код

<UserControl x:Class="TryDP.Page"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    Width="400" Height="300" xmlns:TryDP="clr-namespace:TryDP" 
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d">
    <Grid x:Name="LayoutRoot" Background="White">
     <TryDP:SQ  Margin="80,32,0,0" Height="48" Width="88" Foreground="#FFFF0000" Background="#FFB64B4B" BorderBrush="#FF7D4444"/>
    </Grid>
</UserControl>


Что у меня не так?

Добавлено через 4 минуты и 59 секунд
Еще вопрос.

А если я в контрол вставляю объект у которого нет такого свойства как у UserControl. Например эллипс. У него есть свойство Fill. 
Как проще всего сделать, чтобы изменяя свойство Foreground у UserControl, у эллипса менялось Fill?

Автор: rooks 3.4.2009, 15:42
Вы же выставляете свойства UserControl-у а не кнопке. Чтобы менять свойства кнопки можно биндить их на свойства UserControl-а.

Автор: dazy 3.4.2009, 15:47
Цитата(rooks @ 3.4.2009,  18:42)
Вы же выставляете свойства UserControl-у а не кнопке. Чтобы менять свойства кнопки можно биндить их на свойства UserControl-а.

Да, это я понимаю.
У меня вопрос как это сделать!

Автор: rooks 3.4.2009, 15:59
в данном примере можно вот так
Код
<UserControl ... Name="p">
    <Grid x:Name="LayoutRoot">
        <Button Background="{Binding Path=Background,ElementName=p}" 
                Foreground="{Binding Path=Foreground,ElementName=p}" Content="Button"/>
    </Grid>
</UserControl>
ну и остальные свойства аналогично

или так
Код
        <Button DataContext="{Binding ElementName=p}" 
                Background="{Binding Background}"  
                Foreground="{Binding Foreground}" Content="Button"/>

Автор: dazy 3.4.2009, 16:51
Это наверное для сильверлайта 3 да? У меня на ElementName ругается, говорит не могу узнать слово ))))

Автор: rooks 3.4.2009, 16:55
это для WPF, как для сильверлайта не знаю...

Автор: dazy 7.4.2009, 14:52
Еще раз подниму вопрос надеясь на мировой опыт:

Я могу только переопределить, т.е. по факту написать свое свойство для юзерконтрола:

Код

        public new Brush Foreground // ключевое слово new, так как у Юзерконтрола уже есть такое свойство как Foreground
       //С таким же успехом я бы мог сделать и свойство MyBrush, и точно так же пользоваться им. 

        {
            get { return (Brush)GetValue(ForegroundProperty); }
            set { SetValue(ForegroundProperty, value); }
        }
        public new static readonly DependencyProperty ForegroundProperty =
            DependencyProperty.Register("Foreground", typeof(Brush), typeof(LightControl),
            new PropertyMetadata(null, OnForegroundChanged));

        private static void OnForegroundChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ((LightControl)d).OnForegroundChanged(e);
        }

        protected virtual void OnForegroundChanged(DependencyPropertyChangedEventArgs e)
        {
            //Все что я делаю, это передаю в Fill новую кисть.
            Color.Fill = (Brush) e.NewValue; 
        }


Все что я делаю выше, это передаю в Fill новую кисть. Но это не очень здорово использовать кодбихайнд для привязки, да.
1. Можно ли сделать тоже самое, т.е. использовать стандартное свойство Foreground, чтобы менять цвет у вложенных объектов, без переопределения Foreground? Т.е. можно ли как то подключиться к event'у который срабатывает при изменении свойства?

2. Как можно тоже самое сделать чрез замл? 

Есть простенький контрол:
Код

<UserControl
xmlns= ....
x:Class="TrafficLight.LightControl">
<Grid x:Name="LayoutRoot">
<Grid x:Name="Light" >
  <Ellipse  x:Name="Color" Fill="{Что должно быть здесь, чтобы сюда попало значение Foreground?}" Stroke="#FF000000" />
  <Ellipse  x:Name="Shade" Fill="#E4555555" />
</Grid>
</Grid>


Чтобы потом можно было пользоваться этим Юзерконтролом на страничке таким образом:

Код

<TrafficLight:LightControl x:Name="red" Foreground="#FFFEF100"  --- я хочу чтобы это свойство отвечало за цвет моего UserControl, за цвет у Color.Filll/>



Любые идеи приветствуются!
Все это про силверлайт  smile 

Автор: -Mikle- 7.4.2009, 16:29
Попробуйте вот так, вроде для Silverlight тоже должно работать (для десктоп приложений работает):
Код

            <Ellipse  x:Name="Color" Fill="{Binding Foreground, RelativeSource={RelativeSource AncestorType=UserControl, Mode=FindAncestor}}" Stroke="#FF000000" />

Автор: dazy 7.4.2009, 17:14
К сожалению SL2 не поддерживает RelativeSource smile 

Автор: -Mikle- 7.4.2009, 17:39
а ControlTemplate и TemplateBinding поддерживает?
если да, то дам пример.

Автор: dazy 7.4.2009, 17:56
Вроде да, поддерживает.

ElementName - нет.

Автор: -Mikle- 7.4.2009, 19:03
Тогда советую либо вообще отказаться от UserControl и сделать так:
Код

<Window x:Class="WpfApplication1.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:l="clr-namespace:WpfApplication1"
    Title="Window1" Height="300" Width="300">
    <Window.Resources>
        <ControlTemplate x:Key="myEllipses" TargetType="Button">
            <Grid>
                <Ellipse  x:Name="Color" Fill="{TemplateBinding Foreground}" Stroke="#FF000000" />
                <Ellipse  x:Name="Shade" Fill="#E4555555" />
            </Grid>
        </ControlTemplate>
    </Window.Resources>
....................................
......................
...........................
        <Button Foreground="Blue" Template="{StaticResource myEllipses}" />
.................
........................
..........


либо сделать вот так:
Код

<UserControl x:Class="WpfApplication1.LightControl"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Height="300" Width="300">
    <UserControl.Template>
        <ControlTemplate TargetType="Control">
            <Grid>
                <Ellipse  x:Name="Color" Fill="{TemplateBinding Foreground}" Stroke="#FF000000" />
                <Ellipse  x:Name="Shade" Fill="#E4555555" />
            </Grid>
        </ControlTemplate>
    </UserControl.Template>
</UserControl>


Но что-то мне подсказывает, что в сильверлайте есть таки некий готовый Binding либо его подходящие свойства... уж слишком тривиальная задача, и делать так как я предложил, это мне кажется как через ж**у...  smile 

Автор: dazy 7.4.2009, 20:27
WPF решения не работают.

Во-первых, в СЛ binding действительно кастрированный до предела. Может с выходом 3й версии ситуация изменится.
Во-вторых, похоже, что UserControl, это какое-то половинчатое решение. И чтобы делать более-менее приличный контрол, надо наследоваться от Control. 

Как я понял, при работе с UC, единственный возможный путь биндить свойство на отображение контрола это внутри кода DP.
Чтобы биндить свойство внутри замл, нужно наследоваться от Control, и создавать шаблон, там можно и биндить. 
Так что придется переходить в на использование Control, или забить на замл, и все делать из кода. Или кто-то все же подскажет решение. Но я уже сомневаюсь, что оно вообще существует. По крайней мере во 2й версии СЛ.  smile 

Автор: dazy 8.4.2009, 12:44
Плюнул я на SL2 с его геморойным биндингом. Перешел на 3ю версию. Надеюсь на его скорый оф.релиз.
3ка на голову делает 2ю версию. Пара кликов, и все биндится как в лучших домах.

Автор: -Mikle- 9.4.2009, 20:38
Я по подобной причине перешел на 3.0 и 3.5. Делал в WinForms "нереальные" вещи, гордился что получалось, а потом решил все таки прочитать что такое WPF  smile ... Как мне стало жалко потраченное на WinForms-реализации время... (ну не совсем жалко, т.к. пользы для мозгов было тоже не мало)

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)