PDA

View Full Version : سوال: چگونه یک UserControl ایجاد کنیم که قابلیت نگهداری کنترلهای دیگر را داشته باشد؟



رافعی مهدی
پنج شنبه 17 شهریور 1390, 14:23 عصر
با سلام
[در WPF مبتدی هستم]

در برنامه ای که مینویسم نیاز به ایجاد کنترلی (UserControl) دارم که با XAML بتوانم در اون کنترلهای دلخواهی رو قرار بدم.

برای این کار یک UserControl ایجاد کردم به اسم ContentUserControl:
<UserControl x:Class="ContentUserControl_Project.ContentUserControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*" />
</Grid.RowDefinitions>

<Grid Background="Black" Grid.Row="0">
<TextBlock Text="{Binding Header, ElementName=ContentUserControl}" Foreground="Yellow" TextAlignment="Center" Margin="12, 10, 0, 10" />
</Grid>
<ContentControl HorizontalAlignment="Stretch" HorizontalContentAlignment="Stretch" Content="{Binding Body, ElementName=ContentUserControl}" Grid.Row="1"/>
</Grid>
</UserControl>


در بخش code-behind داریم:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Collections.ObjectModel;

namespace ContentUserControl_Project
{
/// <summary>
/// Interaction logic for ContentUserControl.xaml
/// </summary>
public partial class ContentUserControl : UserControl
{
#region __________________________________________________ ________________________________ Properties

public string Header
{
get;
set;
}

/// <summary>
/// Using a DependencyProperty as the backing store for Body. This enables animation, styling, binding, etc...
/// </summary>
public static readonly DependencyProperty BodyProperty = DependencyProperty.Register("Body",
typeof(object),
typeof(ContentUserControl),
new UIPropertyMetadata(null, ContentUserControl.IsBodyPropertyChanged, IsBodyPropertyCoerce, true));

public object Body
{
get
{
return GetValue(BodyProperty);
}
set
{
// Don't do any custom logic here! Because this accessor section will be ignoed at run-time.
// Instead, do your custom logic at the IsBodyPropertyChanged.
SetValue(BodyProperty, value);
}
}

private static void IsBodyPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var instance = d as ContentUserControl;
if (instance != null)
{
// Do something here..
}
}

private static object IsBodyPropertyCoerce(DependencyObject d, object value)
{
// The value is trying to set on this property..
return value;
}

#endregion


#region __________________________________________________ ________________________________ Events

public ContentUserControl()
{
InitializeComponent();
}

#endregion
}
}


اما زمانی که میخواهم از ContentUserControl استفاده کنم، محتویات Body نمایش داده نمیشوند:


<Window x:Class="ContentUserControl_Project.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:ContentUserControl_Project"
Title="MainWindow" Height="350" Width="525">
<Grid>
<local:ContentUserControl>
<local:ContentUserControl.Body>
<Button>Hello There!</Button>
</local:ContentUserControl.Body>
</local:ContentUserControl>
</Grid>
</Window>


یه راهی به نظرم میرسه، اونم اینه که از IContentHost استفاده کنم. (البته اصلاٌ نمیدونم تز درستی هست یا نه!)

پ.و. کدهای این پست بر اساس توضیحات ارائه شده در اینجا (http://stackoverflow.com/questions/7069630/custom-usercontrol-with-contentcontrol-field) (به اضافه مقداری تغییر) ارائه شده اند.
ممنون میشم اگه دوستان راهنمایی کنن

هاجر22
پنج شنبه 17 شهریور 1390, 23:48 عصر
چرا از blend استفاده نمی کنید؟

رافعی مهدی
جمعه 18 شهریور 1390, 10:38 صبح
از پاسختون ممنونم، نمیدونم در Blend میشه همچین کاری کرد یا نه؟

ولی به هر حال به عقیده من کد نویسی XAML به صورت دستی اگرچه نسبت به نرم افزارهای تولید کننده خودکار XAML (مثل Blend که در کارهای دوبعدی و Zam 3D که در کارهای سه بعدی بسیار قوی هستند) زمانبر تر و البته دشوارتر هست، ولی برای افراد مبتدی مثل من که هنوز روی XAML تسلط ندارند، خیلی مفیدتر هست.

مهدی فرزاد
شنبه 19 شهریور 1390, 00:45 صبح
سلام
اگر امکان داره فایل رو پیوست کنید

رافعی مهدی
شنبه 19 شهریور 1390, 11:16 صبح
فایلهای پروژه به پیوست تقدیم شد.

مشکلاتم رو در کد XAML پنجره اصلی برنامه به صورت comment نوشتم، ممنونم.

مهدی فرزاد
شنبه 19 شهریور 1390, 12:53 عصر
سلام

این رو ببینید

من body رو پاک کردم بجاش یک استایل برای UserControl تعریف کردم که ContentPresenter درون اون رو در ردیف 1 گرید قرار دادم و Bind کردم به Content یوزر کنترل
اینجوری نیازی به پراپرتی بادی نیست

و در بالای اون یعنی سطر 0 گرید ، همون textBlock رو قرار دادم و Bind کردم به Header
<UserControl.Resources>
<Style x:Key="UserControlStyle1" TargetType="{x:Type UserControl}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type UserControl}">
<Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Padding="{TemplateBinding Padding}" SnapsToDevicePixels="true">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="38.1"/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid Background="Black" Grid.Row="0" Margin="0">
<TextBlock x:Name="textBlock" Text="{Binding Header}" Foreground="Yellow" TextAlignment="Center" Margin="10" />
</Grid>
<ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" Grid.RowSpan="1" Grid.Row="1" Content="{TemplateBinding Content}"/>
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</UserControl.Resources>

و در ضمن اینو رو هم در متد سازنده یوزر کنترل نوشتم
public ContentUserControl()
{
InitializeComponent();
DataContext = this;
}

و حالا برای استفاده از یوزر کنترل میتنوید خیلی راحت بنویسید
<local:ContentUserControl x:Name="content" Header="Hi This is OK?">
<StackPanel>
<Button>Hello There! 1</Button>
<Button>Hello There! 2</Button>
<Button>Hello There! 3</Button>
</StackPanel>

</local:ContentUserControl>

شما میتنوید هر کنترل دیگه ای رو توی اون قرار بدید
فقط این نکته رو بدونید که اگر از Panel ها استفاده نکنید فقط یک کنترل رو میتونید در یوزر کنترل قرار بدید پس بهتره مثلا ابتدا یک گرید رو توی اون قرار بدید و بعد به تعداد دلخواه هر کنترلی رو توی اون اضافه کنید
من در مثال بالا از یک StackPanel استفاده کردم

رافعی مهدی
شنبه 19 شهریور 1390, 16:40 عصر
آقای فرزاد، یک دنیا ممنونم!

اگرچه جواب سوالم رو گرفتم، اما با اجازه شما میخواهم حداکثر استفاده رو از پاسختون ببرم. برای همین تصمیم گرفتم تغییراتی که ایجاد کردید رو موشکافانه بررسی کنم و چون بحث همچنان در مورد موضوع همین تاپیک دنبال میشه، تاپیک جدیدی ایجاد نکردم:

[چون بسیار مبتدی هستم، برداشتهای خودم رو مینویسم، هر کجا از اون که اشتباه یا ناقص بود، لطفاً تصحیح یا تکمیل کنید، اگر پاسخ دهی به این همه سوال خیلی وقت شما رو میگیره، لطفاً Reference بدید. باز هم ممنونم.]

1- چرا وقتی پراپرتی Header رو مقدار دهی میکنیم در Design Time اثری نداره؟ (در حالی که کوچکترین تغییری در Content بلافاصله حس میشه.)
البته خودم یه کاری کردم که این مسئله رفع شد ولی نمیدونم آیا بهترین روش ممکن هست یا نه؟

private static void IsHeaderPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var instance = d as ContentUserControl;
if (instance != null)
{
instance.DataContext = instance;
}
}


2- در برنامه ای که من نوشتم، وقتی پراپرتی Header مقدار دهی میشه هیچ تغییری در UI به وجود نمیاد، چرا؟ در حالت کلی استفاده از DataContext چه قانونی داره و اصولاً در Binding چه مقداری رو و در چه زمانی باید set کنیم؟ مثلاً _همانطور که در شماره 1 عرض شد_ برای حس شدن آنی تغییرات Header، نمونه جاری (current instance) از کلاس UserControl به DataContext پاس داده شده، آیا میشد بعنوان نوعی Optimization تنها از e.NewValue استفاده کرد؟

3- در Windows Forms Applications وقتی میخواستیم چیزی شبیه به همین کنترل رو ایجاد کنیم، یه کنترل میساختیم که یه Panel رو دربر گرفته، بعد access modifier اون Panel رو از حالت private به protected تغییر میدادیم، اون وقت UserControl ای که ایجاد کردیم میشد شبیه همین style، و با ارث بری از اون میشد روی Panel مذکور (حتی در DesignTime) هر کنترل دلخواهی رو قرار داد.
حالا سوال اینه که آیا استفاده از style در UserControl ها (در چنین شرایطی) به عنوان یک متد استاندارد در WPF مطرح هست یا کاری که شما کردید، فقط یکی از راههای ممکن هست؟ (اگر راه دیگری هم وجود داره لطفاً بفرمایید.)

4- استفاده از style چه فلسفه ای داره و به طور کلی در چه مواردی باید از اون استفاده کرد؟
(استفاده ای که قبلاً _چند سال پیش_ از style دیده بودم، _حالا اگه درست یادم مونده باشه_ بهره گیری از مجموعه ای از Resourceها بود که apply کردنش روی کنترها نسبت به استفاده منفرد از تک تک آنها بسیار کلاسه بندی شده تر، منظم تر و البته کنترل شده تر بود. چونکه میشد یک style رو پایه یک style دیگه قرار داد و برخی تغییرات رو نسبت به style پایه override کرد.)

5- شما در UserControl یه Style قرار دادید. خود UserControl دارای یک پراپرتی به نام Template هست که الگوی المانهای داخل اون رو مشخص میکنه، داخل style به کمک setter به این پراپرتی مقدار دادید. این کار با استفاده از تگ ControlTemplate صورت گرفته (چرا؟ آیا راه دیگری هم داره؟ DataTemplate چه ربطی به ControlTemplate داره؟ چه موقع در ایجاد Template از اون استفاده میکنیم؟ خلاصه اینکه قانون کلی برای ایجاد Template چیست؟)
مثلاً برای Template تعریف کردن واسه Itemهای یک ListBox میتونیم بنویسیم:
<ListBox x:Name="lstPeople" Width="400">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Path=FirstName}" />
<TextBlock Text=" " />
<TextBlock Text="{Binding LastName}" />
<TextBlock Text=", " />
<TextBlock Text="{Binding Age, TargetNullValue='Age Unknown'}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>

مهدی فرزاد
یک شنبه 20 شهریور 1390, 09:52 صبح
سلام
تعداد سئوال ها زیاد شد ولی سعی میکنم در حد توان جواب بدم
1- چون زمانی که در کد قبلی Header تغییر میکرد DataContext رو تعریف نکرده بودید و زمان اجرا تازه با کد DataContext = this تعریف میشد و پراپرتی Header برای یوزر کنترل شناخته میشد ولی شما با نوشتن این کد instance.DataContext = instance هنگام تغییر پراپرتی DataContext رو هم تعریف میکنید و نتیجه در لحظه نمایش داده میشه ولی یک اشکال وجود داره و اون اینه که بعد از اجرا اگر به محیط طراحی برگردید دیگه عبارتی برای Header نمیبیند تا زمانی که دوباره PropertyChange انتفاق نیوفته چیزی نشون نمیده پس این راه صحیح نیست من کد رو اشتباه نوشتم شما کافی اون کد
DataContext = this رو که من در متد سازنده یوزر کنترل نوشته بودم در Load یوزر کنترل بنویسید و همه چیز درست میشه و نیازی به instance.DataContext = instance نیست
private void UserControl_Loaded(object sender, RoutedEventArgs e)
{
DataContext = this;
}


2- جریان DataContext رو خیلی ساده توضیح میدم فکر کنم تمام ابهامات شما رفع بشه
فرض کنید ما یک کلاس داریم که تعداد زیادی Property توی اون وجود داره و تعدادی هم TextBox داریم که درون یک Grid قرار گرفته و میخوایم هر کدوم از این TextBox ها رو به اون Property ها Bind کنیم پس نیاز داریم برای این کار DataContext مربوط به Grid رو برابر شئی ساخته شده از اون کلاس قرار میدیم با این کار کلیه کنترل هایی که توی اون گرید هستن از وجود اون Property ها با خبر میشن و میتونید اونها رو Bind کنید حالا اگر DataContext ویندوز رو برابر شئی ساخته شده از اون کلاس قرار بدیم کلیه اجزا و کنترل های اون ویندوز هم چنین تمام کنترل هایی که توی استایل اون ویندوز هستن از وجود این Property ها با خبر میشن این مسئله زمانی که شما با Blend کار میکنید کاملا ملموس میشه مثلا تا زمانی که ما DataContext اون Grid رو در Blend معرفی نکنیم هیچ Property در لیست برای Bind کردن نمایش نمیده ولی با تعریف DataContext ، لیست Property های پر میشه ( با تمام جزئیات ) و ما میتونیم هر کدوم رو خواستیم برای Bind انتخاب کنیم ( این ساده ترین توضیحی بود که میتونستم بدم امیدوارم مطلب روشن شده باشه)

3- این کاری که من انجام دادم فقط یک ایده بود و میشه کارهای دیگه هم کردم ( من تست نکردم و الان نمیتونم ایده دیگه ای بدم ) این راه برای این به ذهن من رسید که شما میخواستید Content یوزر کنترل رو فقط در قسمتی از یوزر کنترل قرار بدید نمیخواستید همه یوزر کنترل رو پوشش بده پس من به ذهنم رسید برم و توی استایل یوزر کنترل جای ContentPresenter اون رو تغییر بدم !!

4- خود Style در WPF یک مبحث مفصل هست و خیلی بحث داره اما کلا شما برای تغییر در ظاهر و حالات یک کنترل ( نه منطق کاریش و خصوصیاتش) میتونید دست به ساخت استایل بزنید و این استایل رو میتنوید در ریسورس دیکشنری هم ذخیره کنید تا در برنامه های دیگه هم خیلی راحت با اضافه کردن اون ریسورس دیکشنری برای شما قابل استفاده باشه
منظور من از منطق کاری این هست که مثلا شما با درست کردن یک استابل نمیتونید یک کمبو باکس رو به یک Button تبدیل کنید ، میتونید ظاهرش رو دقیقا مثل button کنید اما خصوصیات Button رو نداره و همچنین یک کمبو باکس باقی میمونه و خصوصیاتی مثل ItemSource و .... دراه به عنوان مثال همین استالی که من در این پست (http://barnamenevis.org/showthread.php?300160-%D9%86%D8%AD%D9%88%D9%87-%D8%B3%D8%A7%D8%AE%D8%AA%D9%86-Expender-%D9%85%D8%A7%D9%86%D9%86%D8%AF-%D9%85%D8%AD%DB%8C%D8%B7-Action-Center-%D8%AF%D8%B1-%D9%88%DB%8C%D9%86%D8%AF%D9%88%D8%B2-7) برای Expander تعریف کردم

5- ItemTemplate مربوط تعریف المان ها و اجزای موجود در هر یک از آیتم های توی کنترل مثلا ListBox هست ItemsPanelTemplate مربوط به نحوه چیدمان و قرار گیری آیتمها در Listbox هست
حالا هر آیتم هم میتونه برای خودش یک استایل داشته باشه یعنی علاوه بر اینکه مثلا ما گفتیم که توش دوتا TextBlock هست ( در ItemTemplate ) و به صورت افقی لیست بشه ( در ItemsPanelTemplate) میتونیم بگیم وقتی موس روش قرار گرفت آبی بشه و وقتی کلیک شد قرمز که این رو در استایل اون آیتم و به عبارتی در
<ControlTemplate TargetType="{x:Type ListBoxItem}">

همچنین میتونیم برای کل List Box که در برگیرنده این آیتم ها هست هم استایل تعریف کنیم
<ControlTemplate TargetType="{x:Type ListBox}">

رافعی مهدی
یک شنبه 20 شهریور 1390, 11:12 صبح
سلام، جوابتون فوق العاده بود!

1- برداشت من اینه که DataContext باعث Binding میشه، بنابراین هرگز نباید اون رو در شرایطی قرار داد که مدام Refresh بشه (یک بار برقراری ارتباط کافی است)، مگر اینکه منظور ما تغییر Binding Source باشه. (درسته؟)

2- برداشت من از پاسخ شما:
DataContext؛ همونطور که از اسمش پیداست مفاد داده های مورد نیاز برای اتصال (Binding) رو در بر میگیره، (حالا اینکه هر آیتم بره و Binding Source مورد نظرش رو پیدا کنه دیگه مربوط به پشت صحنه است و نیازی نیست ما خودمون رو با نحوه ی انجامش درگیر کنیم!) بنابراین مسئله فقط اینه که مقداری که به DataContext پاس داده میشه شامل موارد Reference داده شده در Binding بشه. منتهی اگر بخواهیم محتویات مورد استفاده در Binding فقط مورد استفاده بخش خاصی از UI قرار بگیره، میتونیم بجای this.DataContext از Control>.DataContext> بهره بگیریم. (درسته؟)

3- OK، حالا دیگه شاید توی این تاپیک جاش نباشه که بپرسم فرق ContentControl با ContentPresenter چیه؟ نمیشد در style از ContentControl استفاده کرد؟ (بجز اینکه ContentPresenter سبکتر از ContentControl هست دیگه این انتخاب _با فرض وجود انتخاب برای بکاربستن ContentControl در style_چه مزایای دیگه ای داره؟)

ممنون

رافعی مهدی
چهارشنبه 30 شهریور 1390, 10:09 صبح
با عرض سلام مجدد

پس از تقریبا 10 روز از بکارگیری روش شما با یه مشکل جدی مواجه شدم و مجبور شدم بروم از سایر دوستان (!) در stackOverflow کمک بگیرم و بالاخره (با کمال احترام) متوجه شدم که راه حل شما درست نبوده. هرچند که از اطلاعاتی که داده بودید خیلی استفاده کردم و باز هم در اینجا از شما تشکر میکنم.

برای اطلاع از مشکل به وجود آمده، علتش و چگونگی رفع اون میتونید به اینجا (http://stackoverflow.com/questions/7470621/problem-in-applying-style-on-wpf-usercontrol/7495055#7495055) مراجعه کنید.

epsi1on
چهارشنبه 30 شهریور 1390, 14:36 عصر
1- چرا وقتی پراپرتی Header رو مقدار دهی میکنیم در Design Time اثری نداره؟ (در حالی که کوچکترین تغییری در Content بلافاصله حس میشه.)
البته خودم یه کاری کردم که این مسئله رفع شد ولی نمیدونم آیا بهترین روش ممکن هست یا نه؟

private static void IsHeaderPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var instance = d as ContentUserControl;
if (instance != null)
{
instance.DataContext = instance;
}
}


2- در برنامه ای که من نوشتم، وقتی پراپرتی Header مقدار دهی میشه هیچ تغییری در UI به وجود نمیاد، چرا؟ در حالت کلی استفاده از DataContext چه قانونی داره و اصولاً در Binding چه مقداری رو و در چه زمانی باید set کنیم؟ مثلاً _همانطور که در شماره 1 عرض شد_ برای حس شدن آنی تغییرات Header، نمونه جاری (current instance) از کلاس UserControl به DataContext پاس داده شده، آیا میشد بعنوان نوعی Optimization تنها از e.NewValue استفاده کرد؟

3

سلام دوست من. با اجازه ی برادر فرزاد گرامی فکر کنم جواب این دو سوالتون رو بدونم.
اصولا اگر شی ای که بعنوان دیتا-کانتکس ازش استفاده میشه اینترفیس INotifyProprtyChanged که اگه اشتباه نکنم در فضای نام System.ComponentModel هست (یا جایی با اسمی تو همون مایه ها!) رو پیاده کرده باشه، هروقت پراپرتی ایش تغییر کنه خود به خود چیزی که بهش بایند شده هم از این موضوع مطلع میشه (از طریق خود بایند) و ... . (توضیح واضحات نمیدم دیگه، از گوگل ببینید)
البته من سوالاتتون رو فقط یکبار سریع مرور کردم (بدون تعارف خیلی سخت سوال میپرسید برادر، اگه کسی WPF کار نباشه باید خیلی فکر کنه تا جواب دقیق بده!) و یجورایی فقط جواب مربوط به دو سوال مورد نقل قول شده تو این پست هست. شاید معماری ساخت برنامتون هم یه مقدار چالش برانگیز باشه... در هر حال امیدوارم این پاسخی برای اون دو سوالتون بوده باشه...

رافعی مهدی
پنج شنبه 31 شهریور 1390, 08:01 صبح
سلام عزیزم
از توضیحاتی که دادی ممنونم

حقیقت موضوع اینه که سوالاتی که در این تاپیک مطرح کردم همشون به لطف همون پاسخهای آقای فرزاد که انصافاً هم خوب بودند، حل شده. منتهی یه مسئله ای در استفاده از style برای UserControl ای که به این روش درست کردم به وجود اومد (که البته جزئیات قضیه رو در همون لینکی (http://stackoverflow.com/questions/7470621/problem-in-applying-style-on-wpf-usercontrol) که دادم، به طور کامل تشریح کردم.) حالا شاید بعضی از دوستان نتونند از اون لینک استفاده کنند، خلاصه اش رو همین جا هم میگم:

وقتی یه UserControl میخواهیم درست کنیم، به این معناست که از قبل میدونیم چه Layout ای داره و نیازی نیست که Template اون رو به این شکل با یه Style تعریف کنیم. (چرا؟) چون باعث میشه وقتی بخواهیم پراپرتیهای اون کنترل رو (در محل استفاده از اون کنترل) از طریق یه style مشخص کنیم، در واقع به طور همزمان دو تا style به کنترل اعمال بشوند که باعث نوعی تصادم در مقدار دهی پراپرتیها میشه و این ناسازگاری کنترل رو از کار می اندازه. چاره کار در چنین شرایطی استفاده از CustomControl هاست. در این شرایط ما با یه کنترل Lookless سروکار داریم. (برای اطلاعات بیشتر در مورد LooklessControls میتونید به اینجا (http://www.codeproject.com/KB/WPF/WPFCustomControl.aspx) مراجعه کنید. البته تشریح قضیه رو من در کتاب Pro WPF نوشته Matthew MacDonald فصل 24 صفحه 858 هم خوندم، خیلی خوب توضیح داده، اگر دسترسی داشته باشید بد نیست یه مراجعه ای هم به اون بکنید.) برای اطلاع بیشتر از نحوه ساختن یه CustomControl میتونید به دو تا لینکی که در پایین همون تاپیک StackOverflow دادم مراجعه کنید...

اما در مورد پاسخ شما:
با کمال احترام (ناراحت نشوید) با پاسخی که دادید، مخصوصاً کلمه اصولاً ای که بکار بردید مخالف هستم. حالا چرا؟ چون...

در DataBinding یه ارتباط یک طرفه (با جهت دلخواه) یا دوطرفه بین Source و Target برقرار میشه که Source اون میتونه یه پراپرتی عادی در Net. یا یه Dependency Property باشه ولی Target حتماً باید Dependency Property باشه. برای اینکه DataBinding به درستی عمل کنه، لازمه که هر دو طرف، هرگونه تغییری در مقدار خودشون رو اطلاع بدهند تا بفهمیم که کی لازمه Target توسط مکانیزم بایندینگ Update بشه. حالا، اگه Source یه پراپرتی معمولی باشه، این اطلاع رسانی از طریق رخداد PropertyChanged از اینترفیس INotifyPropertyChanged صورت میگیره ولی اگر Dependency Property باشه، با همون callback مربوط به PropertyChanged متادیتا انجام میشه. یعنی همون طور که در پستهای قبل بهش اشاره شد، دیگه در تکه کدی که نقل قول کردید، درست نبود DataContext معادل instance قرار داده بشه. (که البته این موضوع پیش از این حل شده بود.) این توضیحاتی که دادم رو آقای Christian Moser خیلی قشنگتر از من اینجا (http://www.wpftutorial.net/DataBindingOverview.html)با چندتا شکل و مثال تشریح کرده، امیدوارم علت مخالفتم رو تونسته باشم به طور ساده و گویا بیان کنم (اون ولی اگر پر رنگ و قرمز اصولاٌ ای که بکاربردید رو نقض میکنه) و البته شما رو هم ناراحت نکرده باشم.

موفق باشید

epsi1on
پنج شنبه 31 شهریور 1390, 13:48 عصر
در DataBinding یه ارتباط یک طرفه (با جهت دلخواه) یا دوطرفه بین Source و Target برقرار میشه که Source اون میتونه یه پراپرتی عادی در Net. یا یه Dependency Property باشه ولی Target حتماً باید Dependency Property باشه. برای اینکه DataBinding به درستی عمل کنه، لازمه که هر دو طرف، هرگونه تغییری در مقدار خودشون رو اطلاع بدهند تا بفهمیم که کی لازمه Target توسط مکانیزم بایندینگ Update بشه. حالا، اگه Source یه پراپرتی معمولی باشه، این اطلاع رسانی از طریق رخداد PropertyChanged از اینترفیس INotifyPropertyChanged صورت میگیره ولی اگر Dependency Property باشه، با همون callback مربوط به PropertyChanged متادیتا انجام میشه. یعنی همون طور که در پستهای قبل بهش اشاره شد، دیگه در تکه کدی که نقل قول کردید، درست نبود DataContext معادل instance قرار داده بشه. (که البته این موضوع پیش از این حل شده بود.) این توضیحاتی که دادم رو آقای Christian Moser خیلی قشنگتر از من اینجا (http://www.wpftutorial.net/DataBindingOverview.html)با چندتا شکل و مثال تشریح کرده، امیدوارم علت مخالفتم رو تونسته باشم به طور ساده و گویا بیان کنم (اون ولی اگر پر رنگ و قرمز اصولاٌ ای که بکاربردید رو نقض میکنه) و البته شما رو هم ناراحت نکرده باشم.

سلام مجدد.
نه دوست من، چرا ناراحت بشم. هر انسانی خطا میکنه، چه من چه شما چه ... .یکی از بینهایت اشتباهاتی که توی زندگی انجام میدیم که نباید ناراحتمون کنه.
ولی در مورد پاسختون، منم یه حداقل اطلاعاتی در مورد کلیت WPF و کلا کامپیوتر و موارد مربوطه دارم (اصلا روی مقدارش تاکید ندارم، شاید خیلی کم باشه، کمتر از خیلی از دوستان) ولی در هر حال فرمایش شما نقض عرایض من نیست. میتونه راه حلهای مختلفی برای یه مساله موجود باشه که همش هم نیازهامون رو کامل پاسخ بده.
شما که اصلا پراپرتی Header رو بصورت DependencyProperty پیاده نکرده بودید که این توضیحات رو دادید! اصلا تو سوال دومتون صریحا منظورتون این بود که چطور میشه بدون تغییر دادن DataContext وقتی پراپرتی تغییر میکنه چیزی که بهش بایند شده هم از این قضیه مطلع بشه!

شاید اون موقع که پستم رو نوشتمیه مقدار کمتر از حالت معمول به این که اگه طرف دوم Binding یه DependencyProperty باشه فکر میکردم (مسلما دلیل عمدش هم این بود که شما پراپرتی Header رو DependencyProperty نکرده بودید و فقط پراپرتی معمولی بود) منم اولین راه حلی که به ذهنم رسید گفتم که تمام نیازهای شما رو کامل پاسخ میداد. (اشتباه میکنم؟).
عبارت "اصولا" هم که معنی "فقط" رو نمیده، میده؟

رافعی مهدی
جمعه 01 مهر 1390, 01:46 صبح
- گاهی!

حتماً شما نه تنها از کلیت WPF بلکه از جزئیات اون هم باخبرید، من فکر کردم منظورتون از اصولاً همون فقط هست، وگرنه فرمایشات شما برای منه مبتدی خیلی هم متین و خوبند!
به نظر من بهتره از این بحثها بگذریم. اگر دوست داشتید یه سری به اینجا (http://stackoverflow.com/questions/7512748/changing-listbox-itemspaneltemplate-has-gotten-me-into-trouble/7521217#7521217)بزنید و پاسخ مشکل مطرح شده رو بدید که همچنان استفاده از CustomControl سوال برانگیزه!

epsi1on
جمعه 01 مهر 1390, 13:09 عصر
- گاهی!

حتماً شما نه تنها از کلیت WPF بلکه از جزئیات اون هم باخبرید، من فکر کردم منظورتون از اصولاً همون فقط هست، وگرنه فرمایشات شما برای منه مبتدی خیلی هم متین و خوبند!
به نظر من بهتره از این بحثها بگذریم. اگر دوست داشتید یه سری به اینجا (http://stackoverflow.com/questions/7512748/changing-listbox-itemspaneltemplate-has-gotten-me-into-trouble/7521217#7521217)بزنید و پاسخ مشکل مطرح شده رو بدید که همچنان استفاده از CustomControl سوال برانگیزه!
من کوچکتم دوست من.
والا نگاه میکنم، سعی میکنم اگه سواطم قد داد، نظر بدم... :لبخندساده:
بد نیست اون سوالات رو همینجا هم عنوان کنید تا دوستان و اساتید هم اگه خواستن در موردش نظر بدن...

رافعی مهدی
جمعه 01 مهر 1390, 16:46 عصر
خواهش میکنم، به روی چشم، سرور ما هستید.

سوال در اینجا (http://barnamenevis.org/showthread.php?306351-%D9%85%D8%B4%DA%A9%D9%84-%D8%AF%D8%B1-%D8%AA%D8%BA%DB%8C%DB%8C%D8%B1-ItemsPanelTemplate-%DB%8C%DA%A9-ListBox&p=1344202#post1344202) هم مطرح شد!