Здравствуйте, Sinix, Вы писали:
S>Здравствуйте, ICEMAN3141592, Вы писали:
S>Посмотрел код, понял в чём ваши грабли. DataContext каждого элемента в ListView содержит соответствующий элемент из ItemsSource. Соответственно, до родительского DataContext можно добраться только через извраты аля {RelativeSouce ...}. Проще передавать DataMatrix через StaticResource.
Сейчас попробую через StaticResources, хорошая идея (даже очень). Не отходите далеко, пожалуйста
WPF. Доступ к объекту параметра конвертера в методе Convert
От:
Аноним
Дата:
29.05.11 11:26
Оценка:
Проблема: как получить из свойства класса объект, который можо было использовать как параметр конвертера
Извините, если не правильно оформил, очень спешу, много времени потратил, задолбался. Ведь DataMatrix="{Binding DataMatrix}" так нельзя писать, Converter не DependencyObject, тогда как присобачить параметр-свойство из класса- владельца окна ?
Спасибо.
Re: WPF. Доступ к объекту параметра конвертера в методе Conv
Здравствуйте, Аноним, Вы писали:
А>Converter не DependencyObject, тогда как присобачить параметр-свойство из класса- владельца окна ?
1. DataMatrix={StaticResource someResource} (только тут проще будет использовать ConverterParameter Binding-а).
2. А что мешает унаследовать converter от DependencyObject?
Re: WPF. Доступ к объекту параметра конвертера в методе Conv
Re[2]: WPF. Доступ к объекту параметра конвертера в методе C
От:
Аноним
Дата:
29.05.11 12:30
Оценка:
Здравствуйте, Sinix, Вы писали:
S>Здравствуйте, Аноним, Вы писали:
А>>Converter не DependencyObject, тогда как присобачить параметр-свойство из класса- владельца окна ?
S>1. DataMatrix={StaticResource someResource} (только тут проще будет использовать ConverterParameter Binding-а). S>2. А что мешает унаследовать converter от DependencyObject?
Да я пытаюсь, что то не как. Я делал 2ое, но он говорил, что DependencyProperty может быть только у DepdendencyObject (каким я свой конвертер и сделал, каким и сделал нужное мне его свойство).
<ListView Name="lvwCycleTable" Margin="3">
<ListView.View>
<GridView>
<GridView.Columns>
<GridViewColumn>
<GridViewColumn.HeaderTemplate>
<DataTemplate>
<TextBlock Margin="5" Text="Цикл" />
</DataTemplate>
</GridViewColumn.HeaderTemplate>
<GridViewColumn.DisplayMemberBinding>
<Binding Path="Vertexes">
<Binding.Converter>
<local:CycleConverter DataMatrix="{Binding DataMatrix}" />
</Binding.Converter>
</Binding>
</GridViewColumn.DisplayMemberBinding>
</GridViewColumn>
</GridView.Columns>
</GridView>
</ListView.View>
</ListView>
//-------------------------------------------------------------------------------
class CycleConverter : DependencyObject, IValueConverter
{
static CycleConverter()
{
DataMatrixProperty = DependencyProperty.Register("DataMatrix", typeof(DataMatrix), typeof(CycleConverter), new FrameworkPropertyMetadata(null, new PropertyChangedCallback(OnDataMatrixChanged)));
}
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
// Здесь value будет взаимодействовать с parameter
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
private static void OnDataMatrixChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
// ListView listView = d as ListView;
DataMatrix dataMatrix = e.NewValue as DataMatrix;
_dataMatrix = dataMatrix;
}
private static DataMatrix _dataMatrix = null;
public static readonly DependencyProperty DataMatrixProperty;
public DataMatrix DataMatrix
{
get
{
return (DataMatrix)GetValue(DataMatrixProperty);
}
set
{
SetValue(DataMatrixProperty, value);
}
}
}
//-------------------------------------------------------------------------------
public MainWindow()
{
InitializeComponent();
this.DataContext = new DataMatrix();
List<Cycle> cycles = new List<Cycle>();
lvwCycleTable.ItemsSource = cycles;
}
public class Cycle
{
public Cycle()
{
for (Int32 i = 0; i < 10; i++)
{
list.Add(i);
}
}
public List<Int32> Vertexes
{
get
{
return list;
}
}
List<Int32> list = new List<Int32>();
}
//-------------------------------------------------------------------------------
class DataMatrix
{
public DataMatrix()
{
String a = "a";
for (Int32 i = 0; i < 10; i++)
{
list.Add(a + i);
}
}
public String GetShortName(Int32 index)
{
return list[index];
}
private List<String> list = new List<String>();
}
Re[2]: WPF. Доступ к объекту параметра конвертера в методе C
Здравствуйте, Sinix, Вы писали:
S>Здравствуйте, Аноним, Вы писали:
S>Забыл S>3. MultiBinding.
Так MultiBinding нужен, если много свойств объекта нужно для формирования контента. А мне нужно получить ПАРАМЕТР для конвертера. У меня есть ListView, я в XAML привязал столбцам свойство объекта (Path), в коде указал на коллекцию объектов (ItemsSource), в XAML указал свой конвертер, теперь нужно просто соединить конвертер и его параметр (parameter), так как значение (value) уже будет.
Re[2]: WPF. Доступ к объекту параметра конвертера в методе C
Здравствуйте, Sinix, Вы писали:
S>Здравствуйте, Аноним, Вы писали:
А>>Converter не DependencyObject, тогда как присобачить параметр-свойство из класса- владельца окна ?
S>1. DataMatrix={StaticResource someResource} (только тут проще будет использовать ConverterParameter Binding-а). S>2. А что мешает унаследовать converter от DependencyObject?
DataMatrix- это тот объект, который должен быть параметром для конвертера.
Re[3]: WPF. Доступ к объекту параметра конвертера в методе C
Посмотрел код, понял в чём ваши грабли. DataContext каждого элемента в ListView содержит соответствующий элемент из ItemsSource. Соответственно, до родительского DataContext можно добраться только через извраты аля {RelativeSouce ...}. Проще передавать DataMatrix через StaticResource.
Re[4]: WPF. Доступ к объекту параметра конвертера в методе C
Здравствуйте, Sinix, Вы писали:
S>Здравствуйте, ICEMAN3141592, Вы писали:
S>Посмотрел код, понял в чём ваши грабли. DataContext каждого элемента в ListView содержит соответствующий элемент из ItemsSource. Соответственно, до родительского DataContext можно добраться только через извраты аля {RelativeSouce ...}. Проще передавать DataMatrix через StaticResource.
Увы и ах... (тут идет мат- перемат...)
public MainWindow()
{
InitializeComponent();
// this.DataContext = new DataMatrix();
try
{
DataMatrix dataMatrix = this.Resources["DataMatrix2"] as DataMatrix;
dataMatrix = new DataMatrix("b");
}
catch (Exception)
{
Int32 t = 0;
}
List<Cycle> cycles = new List<Cycle>();
lvwCycleTable.ItemsSource = cycles;
}
//--------------------------------------------------------------------
public class DataMatrix
{
public DataMatrix()
{
}
public DataMatrix(String a)
{
for (Int32 i = 0; i < 10; i++)
{
list.Add(a + i);
}
}
public String GetShortName(Int32 index)
{
return list[index];
}
private List<String> list = new List<String>();
}
//---------------------------------------------------------------------
<Window.Resources>
<local:DataMatrix x:Key="DataMatrix2" />
</Window.Resources>
<Grid>
<ListView Name="lvwCycleTable" Margin="3">
<ListView.View>
<GridView>
<GridView.Columns>
<GridViewColumn>
<GridViewColumn.HeaderTemplate>
<DataTemplate>
<TextBlock Margin="5" Text="Цикл" />
</DataTemplate>
</GridViewColumn.HeaderTemplate>
<GridViewColumn.DisplayMemberBinding>
<Binding Path="Vertexes">
<Binding.Converter>
<local:CycleConverter DataMatrix="{StaticResource DataMatrix2}" />
</Binding.Converter>
</Binding>
</GridViewColumn.DisplayMemberBinding>
</GridViewColumn>
</GridView.Columns>
</GridView>
</ListView.View>
</ListView>
</Grid>
//----------------------------------------------------------------
class CycleConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
// Здесь value будет взаимодействовать с parameter
/* List<Int32> vertexes = value as List<Int32>;
StringBuilder cycleBuilder = new StringBuilder(vertexes.Capacity);
Int32 i = 0;
for (; i < vertexes.Count — 1; i++)
{
cycleBuilder.Append(_dataMatrix.GetShortName(vertexes[i])).Append(" -> ");
}
cycleBuilder.Append(vertexes[vertexes[i]]);
*/
DataMatrix d = parameter as DataMatrix;
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
private DataMatrix _dataMatrix = null;
public DataMatrix DataMatrix
{
get
{
return _dataMatrix;
}
set
{
_dataMatrix = value;
}
}
}
Ничего не выводится
Re[5]: WPF. Доступ к объекту параметра конвертера в методе C
Здравствуйте, ICEMAN3141592, Вы писали:
ICE>Так, для StaticResource работает, а вот для DynamicResource зависмое свойство DataMatrix в функции Convert — null.
Если вы не изменяете ресурс после InitializeComponent — всё должно работать. Смотрите сообщения об ошибках в окне output.
Re[3]: WPF. Доступ к объекту параметра конвертера в методе C
Здравствуйте, Sinix, Вы писали:
S>Здравствуйте, ICEMAN3141592, Вы писали:
ICE>>Так, для StaticResource работает, а вот для DynamicResource зависмое свойство DataMatrix в функции Convert — null.
S>Если вы не изменяете ресурс после InitializeComponent — всё должно работать. Смотрите сообщения об ошибках в окне output.
В конструктор приходит параметр DataMatrix, где мне связать с "this.Resources", чтобы этот параметр стал параметром для конвертера ?
public MainWindow(DataMatrix dataMatrix)
{
InitializeComponent();
Здравствуйте, Sinix, Вы писали:
S>Здравствуйте, ICEMAN3141592, Вы писали:
ICE>>Так, для StaticResource работает, а вот для DynamicResource зависмое свойство DataMatrix в функции Convert — null.
S>Если вы не изменяете ресурс после InitializeComponent — всё должно работать. Смотрите сообщения об ошибках в окне output.
Output молчит.
class CycleConverter : DependencyObject, IValueConverter
{
static CycleConverter()
{
DataMatrixProperty = DependencyProperty.Register("DataMatrix", typeof(DataMatrix), typeof(CycleConverter), new FrameworkPropertyMetadata(null, new PropertyChangedCallback(OnDataMatrixChanged)));
}
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
// Здесь value будет взаимодействовать с parameter
DataMatrix d = parameter as DataMatrix;
if (d != null)
{
return DataMatrix.GetShortName(0);
}
if (DataMatrix != null)
{
return DataMatrix.GetShortName(0);
}
return -1;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
private static void OnDataMatrixChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
CycleConverter cycleConverter = d as CycleConverter;
cycleConverter.DataMatrix = e.NewValue as DataMatrix;
}
public static readonly DependencyProperty DataMatrixProperty;
public DataMatrix DataMatrix
{
get
{
return (DataMatrix)GetValue(DataMatrixProperty);
}
set
{
SetValue(DataMatrixProperty, value);
}
}
}
//-----------------------------------------------------------------
<GridViewColumn.DisplayMemberBinding>
<Binding Path="Test">
<Binding.Converter>
<local:CycleConverter DataMatrix="{StaticResource DataMatrix2}" />
</Binding.Converter>
</Binding>
</GridViewColumn.DisplayMemberBinding>
При статическом ресурсе, "DataMatrix d = parameter as DataMatrix;" d не null, при динамическом — null... Мне кажется, что я что- то не то делаю в OnDataMatrixChanged.
Re[4]: WPF. Доступ к объекту параметра конвертера в методе C
Здравствуйте, ICEMAN3141592, Вы писали:
ICE>При статическом ресурсе, "DataMatrix d = parameter as DataMatrix;" d не null, при динамическом — null... Мне кажется, что я что- то не то делаю в OnDataMatrixChanged.
1. this.Resources["DataMatrix2"] = dataMatrix; должно быть перед InitializeComponent();
2. У вас тонна ошибок в CycleConverter.
if (d != null) // Зачем тут d, если мы его не используем???
{
return DataMatrix.GetShortName(0);
}
if (DataMatrix != null)
{
return DataMatrix.GetShortName(0);
}
// ...
// Зачем???private static void OnDataMatrixChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
CycleConverter cycleConverter = d as CycleConverter;
cycleConverter.DataMatrix = e.NewValue as DataMatrix;
}
3. Как parameter может быть не null, если он берёт значение из свойства ConverterParameter Binding-а, которому вы ничего не присваиваете?
Без обид, настоятельно советую подучить матчасть перед тем, как пытаться использовать WPF в продакшне.
Re[5]: WPF. Доступ к объекту параметра конвертера в методе C
Здравствуйте, Sinix, Вы писали:
S>Здравствуйте, ICEMAN3141592, Вы писали:
ICE>>При статическом ресурсе, "DataMatrix d = parameter as DataMatrix;" d не null, при динамическом — null... Мне кажется, что я что- то не то делаю в OnDataMatrixChanged.
S>1. this.Resources["DataMatrix2"] = dataMatrix; должно быть перед InitializeComponent(); S>2. У вас тонна ошибок в CycleConverter. S>
S> if (d != null) // Зачем тут d, если мы его не используем???
S> {
S> return DataMatrix.GetShortName(0);
S> }
S> if (DataMatrix != null)
S> {
S> return DataMatrix.GetShortName(0);
S> }
S>// ...
S> // Зачем???
S> private static void OnDataMatrixChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
S> {
S> CycleConverter cycleConverter = d as CycleConverter;
S> cycleConverter.DataMatrix = e.NewValue as DataMatrix;
S> }
S>
S>3. Как parameter может быть не null, если он берёт значение из свойства ConverterParameter Binding-а, которому вы ничего не присваиваете?
S>Без обид, настоятельно советую подучить матчасть перед тем, как пытаться использовать WPF в продакшне.
Здравствуйте, Sinix, Вы писали:
S>Здравствуйте, ICEMAN3141592, Вы писали:
ICE>>При статическом ресурсе, "DataMatrix d = parameter as DataMatrix;" d не null, при динамическом — null... Мне кажется, что я что- то не то делаю в OnDataMatrixChanged.
S>1. this.Resources["DataMatrix2"] = dataMatrix; должно быть перед InitializeComponent(); S>2. У вас тонна ошибок в CycleConverter. S>
S> if (d != null) // Зачем тут d, если мы его не используем???
S> {
S> return DataMatrix.GetShortName(0);
S> }
S> if (DataMatrix != null)
S> {
S> return DataMatrix.GetShortName(0);
S> }
S>// ...
S> // Зачем???
S> private static void OnDataMatrixChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
S> {
S> CycleConverter cycleConverter = d as CycleConverter;
S> cycleConverter.DataMatrix = e.NewValue as DataMatrix;
S> }
S>
S>3. Как parameter может быть не null, если он берёт значение из свойства ConverterParameter Binding-а, которому вы ничего не присваиваете?
S>Без обид, настоятельно советую подучить матчасть перед тем, как пытаться использовать WPF в продакшне.
1. 'Set property 'System.Windows.ResourceDictionary.DeferrableContent' threw an exception.' Line number '5' and line position '41'. Интересно, как будет присваиваться тому, чего нету ? (Согласен, мой вопрос где должно располагаться " this.Resources["DataMatrix2"]" глуп был, я просто печатал, думав о другом, но как Вы можете этого не знать ?
3. "Как parameter может быть не null, если он берёт значение из свойства ConverterParameter Binding-а, которому вы ничего не присваиваете?"---------- Я просто решил попробовать 2ой вар — сделать обычный конвертер (не наследником DependencyObject), убрать его свойство зависимости DataMatrix, а сделать объект, который будет наследником DependencyObject И он будет в XAML- е играть роль ConverterParameter, а его свойство DataMatrix — свойство зависимости (те же яйца только сбоку ) и просто не убрал "d", НО при StaticResource/DynamicREsource была та же ситуация...
В функции Convert(...)
{
...
DataMatrix d = parameter as DataMatrix;
if (d != null)
{
return DataMatrix.GetShortName(0);
}
if (DataMatrix != null)
{
return DataMatrix.GetShortName(0);
}
return -1;
}
2. // Зачем??? S> private static void OnDataMatrixChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) S> { S> CycleConverter cycleConverter = d as CycleConverter; S> cycleConverter.DataMatrix = e.NewValue as DataMatrix; S> }
---------- ну везде пишут, в метаданных обработчик, честно говоря, я особо и не задумывался, что может это не быть важным в данной ситуации, и что без этого будет работать, да, косяк, признаю.
Ошибки, как Вы сказали, "есть", просто я перебираю возможные варианты (очко дрожит, не успеваю), я делаю UNDO, и Вам отсылаю вариант, который был раньше. Поэтому вы получаете ситуацию где- то посередине... Но я благодарен Вам, что Вы отозвались.
А по поводу "S>Без обид, настоятельно советую подучить матчасть перед тем, как пытаться использовать WPF в продакшне."--------- ну, мне просто некогда сейчас повторять моменты, я просто что- то знаю, что- то помню, что помню, пытаюсь на ощупь найти.
Re[5]: WPF. Доступ к объекту параметра конвертера в методе C
Здравствуйте, Sinix, Вы писали:
S>Здравствуйте, ICEMAN3141592, Вы писали:
ICE>>При статическом ресурсе, "DataMatrix d = parameter as DataMatrix;" d не null, при динамическом — null... Мне кажется, что я что- то не то делаю в OnDataMatrixChanged.
S>1. this.Resources["DataMatrix2"] = dataMatrix; должно быть перед InitializeComponent(); S>2. У вас тонна ошибок в CycleConverter. S>
S> if (d != null) // Зачем тут d, если мы его не используем???
S> {
S> return DataMatrix.GetShortName(0);
S> }
S> if (DataMatrix != null)
S> {
S> return DataMatrix.GetShortName(0);
S> }
S>// ...
S> // Зачем???
S> private static void OnDataMatrixChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
S> {
S> CycleConverter cycleConverter = d as CycleConverter;
S> cycleConverter.DataMatrix = e.NewValue as DataMatrix;
S> }
S>
S>3. Как parameter может быть не null, если он берёт значение из свойства ConverterParameter Binding-а, которому вы ничего не присваиваете?
S>Без обид, настоятельно советую подучить матчасть перед тем, как пытаться использовать WPF в продакшне.
Вы имели ввиду при "this.Resources["DataMatrix2"] = dataMatrix; должно быть перед InitializeComponent();"
удалить
<Window.Resources>
<local:DataMatrix x:Key="DataMatrix2" />
</Window.Resources>
?
Re[6]: WPF. Доступ к объекту параметра конвертера в методе C
Здравствуйте, ICEMAN3141592, Вы писали:
ICE>1. 'Set property 'System.Windows.ResourceDictionary.DeferrableContent' threw an exception.' Line number '5' and line position '41'.
Перед тем, как советовать — проверил. На WPF 4 спокойно прожевало и не подавилось.
public partial class MainWindow : Window
{
public MainWindow()
{
Resources["txt"] = "Hello!!!";
InitializeComponent();
}
}
ICE>Интересно, как будет присваиваться тому, чего нету ?
В момент вызова конструктора Resources уже проинициализированы, так что причина ошибки не в этом. Скорее всего, вы изменяете значение ресурса, который _уже_ объявлен в xaml-е. Угадал?
ICE>НО при StaticResource/DynamicREsource была та же ситуация...
DynamicResource в принципе не будет работать с ConverterParameter. Что-то вы не договариваете
ICE>ну везде пишут, в метаданных обработчик, честно говоря, я особо и не задумывался.
Вопррос не в том, зачем обработчик. Вопрос — нафига присваивать в обработчике свойства (что уже bad practice) _уже_ присвоенное значение?
ICE>ну, мне просто некогда сейчас повторять моменты, я просто что- то знаю, что- то помню, что помню, пытаюсь на ощупь найти.
В таком случае советую отказаться от WPF. Тут или понимаешь, что и зачем, или разгребаешь свои же грабли.
Re[7]: WPF. Доступ к объекту параметра конвертера в методе C
Здравствуйте, Sinix, Вы писали:
S>Здравствуйте, ICEMAN3141592, Вы писали:
ICE>>1. 'Set property 'System.Windows.ResourceDictionary.DeferrableContent' threw an exception.' Line number '5' and line position '41'. S>Перед тем, как советовать — проверил. На WPF 4 спокойно прожевало и не подавилось.
S>Пруф: S>
S> public partial class MainWindow : Window
S> {
S> public MainWindow()
S> {
S> Resources["txt"] = "Hello!!!";
S> InitializeComponent();
S> }
S> }
S>
ICE>>Интересно, как будет присваиваться тому, чего нету ? S>В момент вызова конструктора Resources уже проинициализированы, так что причина ошибки не в этом. Скорее всего, вы изменяете значение ресурса, который _уже_ объявлен в xaml-е. Угадал?
ICE>>НО при StaticResource/DynamicREsource была та же ситуация... S>DynamicResource в принципе не будет работать с ConverterParameter. Что-то вы не договариваете
ICE>>ну везде пишут, в метаданных обработчик, честно говоря, я особо и не задумывался. S>Вопррос не в том, зачем обработчик. Вопрос — нафига присваивать в обработчике свойства (что уже bad practice) _уже_ присвоенное значение?
ICE>>ну, мне просто некогда сейчас повторять моменты, я просто что- то знаю, что- то помню, что помню, пытаюсь на ощупь найти. S>В таком случае советую отказаться от WPF. Тут или понимаешь, что и зачем, или разгребаешь свои же грабли.
Заключение:
Спасибо ВСЕМ, ко принял участие в решении моей проблеме (а это был между прочим 1 Человек). Работает.
Sinix, я нашел еще один вар, но конечно, не такой красивый как у тебя, но рабочий (код вроде всеь скопировал).
GridView view = new GridView();
GridViewColumn col = new GridViewColumn();
Binding binding = new Binding();
binding.Path = new PropertyPath("Test");
CycleConverter cycleConverter = new CycleConverter();
cycleConverter.DataMatrix = new DataMatrix("b");
binding.Converter = cycleConverter;
col.DisplayMemberBinding = binding;
TextBlock textBlock = new TextBlock(new Run("Цикл"));
textBlock.Margin = new Thickness(5.0);