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


Автор: Человек01 13.3.2009, 18:39
Диспозиция:
Определяю набор стилей в отдельном файле, допустим mystyles.xaml:

Код

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:evrika="clr-namespace:DataGridTreeViewMy">
 ....
 <Style x:Key="texbox">
    ....
</Style>
...
</ResourceDictionary>


Потом хочу применить определенные стили из этого файла к определенным элементам.

Понятно если из дизайнера делать, то сначала:
<ResourceDictionary.MergedDictionaries>
    <ResourceDictionary Source="mystyles.xaml" />
  </ResourceDictionary.MergedDictionaries>

А далее, вот что делать?

Вопрос: Какой синтаксис должен быть для доступа к ним, из кода и(или) из дизайнера xaml 
P.S.:Вариант с 
 <Style x:Key="{x:Type TextBox}" TargetType="{x:Type TextBox}" ....
что бы автоматом ко всем TextBox применялась, не подходит. 

Автор: Человек01 13.3.2009, 20:23
Ответ
main.xaml
Код

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Style x:Key="textblok" TargetType="{x:Type TextBox}" >
        <Setter Property="Background" Value="Red"/>
    </Style>
</ResourceDictionary>


В рабочем файле:
Код

<Window x:Class="test01.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:wpf="clr-namespace:Microsoft.Windows.Controls;assembly=WpfToolkit"        
    xmlns:local="clr-namespace:test01"
    xmlns:ComponentModel="clr-namespace:System.ComponentModel;assembly=WindowsBase"
    xmlns:evrika="clr-namespace:DataGridTreeViewMy;assembly=DataGridTreeView"
    Title="Window1" Height="300" Width="300">
    <Window.Resources>
        <ResourceDictionary >
            <ResourceDictionary.MergedDictionaries >
                <ResourceDictionary Source ="main.xaml" />
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Window.Resources>
    <Grid>        
        <TextBox Name="qwe" Style="{StaticResource textblok}">asdfjalsdkj</TextBox>
    </Grid>    
</Window>


либо из кода:
qwe.Style = (Style)this.Resources["textblok"];

P.S.: Извините за простецкий вопрос, просто, что то парился и не получалось в сложном проекте, сделал для пробы простенький, все получилось, видимо я где то стиль на Load переопределяю  smile 

Автор: Человек01 13.3.2009, 21:29
В продолжение темы:
Диспозиция:
Создаю класс:
Код

public class ExTextBox : TextBox
{
    public ExTextBox()
       : base()
    {
           this.Loaded += new RoutedEventHandler(ExTextBox_Loaded);
    }
    
    void ExTextBox_Loaded(object sender, RoutedEventArgs e)
     {
            //как вот здесь применить стиль из main.xaml
            //Собствено main.xaml находится в проекте
     }
}


Вопрос: собственно в коде  smile 
Пробовал так:
Код

StreamResourceInfo s = Application.GetResourceStream(new Uri("main.xaml", UriKind.Relative));
StreamReader sr1 = new StreamReader(s.Stream);
string xamlString = sr1.ReadToEnd();
ResourceDictionary dic = (ResourceDictionary)XamlReader.Parse(xamlString);

Но ошибка
Цитата

" ", шестнадцатеричное значение 0x0C, является недопустимым знаком. Строка 1, позиция 1.

Что делать?

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

StreamResourceInfo s = Application.GetResourceStream(new Uri("main.xaml", UriKind.Relative));
StreamReader sr1 = new StreamReader(s.Stream);
string xamlString = sr1.ReadToEnd();            
System.Windows.Markup.XamlReader reader = new System.Windows.Markup.XamlReader();
ResourceDictionary dic = (ResourceDictionary)reader.LoadAsync(s.Stream);

Тогда ошибка:
Цитата

Отсутствует корневой элемент.


Может это наведёт кого на мысль... Что то я уже париться начинаю. smile 

Автор: Человек01 13.3.2009, 21:53
Для примера:
1.Расположить рядом с исполняемым файлом main.xaml
2.И сделать так:
Код

void ExTextBox_Loaded(object sender, RoutedEventArgs e)
{
          System.IO.Stream s = System.IO.File.OpenRead("main.xaml");
          ResourceDictionary dic = (ResourceDictionary)System.Windows.Markup.XamlReader.Load(s);
          this.Style = (Style)dic["textblok"];
}

То всё работает!
Соответственно остаётся вопрос, как получить main.xaml который находится в самом проекте, со всеми вытекающими?



Автор: Человек01 13.3.2009, 22:31
Всё разобрался.  smile 
Как я понял проблема была в том что XamlReader.Load работает с StreamResourceInfo(s).ContentType = application/xaml+xml
а  Application.GetResourceStream получал application/baml+xml с которым работает Application.LoadComponent
Вот:
Код

void ExTextBox_Loaded(object sender, RoutedEventArgs e)
{
             StreamResourceInfo s = Application.GetResourceStream(new Uri("main.xaml", UriKind.Relative));
            ResourceDictionary rdic = (ResourceDictionary)Application.LoadComponent(new Uri("main.xaml", UriKind.Relative));
            this.Style = (Style)rdic["textblok"];
}

Вот, пользуемся и говорим Человеку спасибо  smile 


Автор: Partizan 13.3.2009, 22:35
Человек01, если main.xaml представляет собой ResourceDictionary со стилями, то достаточно просто ResourceDictionary получить из xaml

как-то так:
.
Код

Uri stylesUri = new Uri("main.xaml", UriKind.Unknown);
ResourceDictionary resources = new ResourceDictionary(stylesUri);


p.s. может и нескомпилиться...по памяти писал...

если отвалится в рантайме, то можно при создании объекта Uri прописать абсолютный путь в синтаксисе pack://...

Добавлено через 1 минуту и 53 секунды
Человек01, ты б взял книжку какую...Adam Nathan "WPF Unleashed" - хорошая книжка...ну или Петцольда на крайний случай...сразу половина вопросов отпадёт...

Автор: PashaPash 13.3.2009, 22:43
Человек01, о как набежали все помогать smile
судя по invalid character, у тебя main.xaml как Embedded Resource лежит, т.е. не xaml, а baml.
Код

            ResourceDictionary dict = (ResourceDictionary)Application.LoadComponent(new Uri("main.xaml", UriKind.Relative));
            this.Resources.MergedDictionaries.Add((ResourceDictionary)dict);

Автор: Partizan 13.3.2009, 22:47
Цитата

о как набежали все помогать


PashaPash, не набежали, а вернулись с работы)

Автор: Человек01 13.3.2009, 23:01
Вот что бывает если не успеешь галочку "Пометить как решённый" поставить  smile 
Где же вы братцы были четыре часа назад  smile 

Partizan,  а UriKind.Unknown - у меня что то нет такого параметра, а с new ResourceDictionary вообще не принимает параметров. Или я что то не так делаю?

А по поводу книг, у меня в наличии только Мэтью Мак-Дональд WPF в NET 3.5
А вообще с книгами такими, у нас в городе проблемы, хорошо если доходят через год-полтора. 
Заказывать, - идет долго, я от ожидания сума сойду smile 
А скачать, не знаю что качать... Ткните пальцем (имеется в виде даже не ссылки, а просто названия, желательно с приблизительным качеством и ориентированностью содержания  smile )
Если честно единственная связь с миром, вот форум (хоть какое то профессиональное общение  smile ).

PashaPash,  спасибо за ответ, мне нравится, - элегантненько. Хотя мой способ тоже работает.

P.S.: Ага набежали вы сразу, скопом, явно ждали...

Автор: Partizan 13.3.2009, 23:04
Человек01
Код

            Uri stUri = new Uri("Dictionary1.xaml", UriKind.RelativeOrAbsolute);
            ResourceDictionary rd = new ResourceDictionary();
            rd.Source = stUri;

Автор: Человек01 13.3.2009, 23:14
PartizanСпасибо работает.
В продолжение темы новый вопрос.
Диспозиция:
проделываю всё вышесказанное в
public class ExTextBox : TextBox
и определяю его в dll 
далее по тексту, в новом приложении прикрепляю dll(содержащий ExTextBox) как References
пытаюсь поставить в приложение ExTextBox, с наивной надеждой что то вставиться со всеми применёнными стилями, но не чаго не получается, кроме:
Цитата

Не удается найти ресурс "main.xaml".

Как поступить?
Цель у меня такая:  ExTextBox наследованный от TextBox в котором я определяю его поведение, реагирование на Eventы и добавляю несколько параметров public String qwe{get;set;}, так же настраивается внешний вид(Вот с последним и бьюсь)
Может у меня просто не правильный подход, для достижения данной цели?



Автор: PashaPash 14.3.2009, 02:29
Цитата(Человек01 @  13.3.2009,  23:14 Найти цитируемый пост)
пытаюсь поставить в приложение ExTextBox, с наивной надеждой что то вставиться со всеми применёнными стилями, но не чаго не получается

Цитата(Partizan @  13.3.2009,  22:35 Найти цитируемый пост)
если отвалится в рантайме, то можно при создании объекта Uri прописать абсолютный путь в синтаксисе pack://...

http://msdn.microsoft.com/en-us/library/aa970069.aspx

Автор: Человек01 14.3.2009, 07:44
PashaPash, огромнейшее спасибо.
Сделал так:
Код

void ElTextBox_Loaded(object sender, RoutedEventArgs e)
{
            Uri stUri = new Uri("/test01;component/main.xaml", UriKind.RelativeOrAbsolute);
            ResourceDictionary rdic = (ResourceDictionary)Application.LoadComponent(stUri);
            this.Style = (Style)rdic["textblok"];
}

в надежде что test01.dll будет всегда рядышком с исполняемым файлом
Работает, Всем ещё раз огромнейшее спасибо.  smile 

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