PDA

View Full Version : دسترسی به داده ای از درون پنجره های مختلف



hamed jalili
پنج شنبه 25 خرداد 1391, 19:40 عصر
با سلام ،

من می خواهم یک و یا چند داده ای را در w1 (شکل زیر ) تعریف کنم مانند :



public ObservableCollection<Defined_Lists> DL = new ObservableCollection<Defined_Lists>();
public Hashtable HT1 = new Hashtable();



و بتوانم از این داده (ها) در w2, w3, ... استفاده کنم به این صورت که این داده (ها) در تمامی w ها قابل خواندن و تغییر باشد و هر تغییری در کل w ها اعمال شود. چون حجم و تعداد داده ها می تواند زیاد باشد ، بنابراین ارسال یک کپی از هر داده به هر کدام از w ها و سپس مانیتور کردن تغییرات و اعمال تغییرات در بقیه کپی ها نمی تواند راهکار مفیدی باشد.

روشی که من در نظر دارم به این صورت است که : کل داده ها را در داخل یک کلاس به صورت public تعریف می کنم ، یک instance ی از این کلاس در w1 ایجاد میکنم ولی مشکل اینجاست که چه طور می توانم از داخل مثلا w2 یا w7 به این کلاس دسترسی داشته باشم ؟

توضیح در مورد شکل : w2, w3 و w4 از داخل w1 فراخوانی میشوند به همین صورت w5 از داخل w4 و w6, w7 از داخل w5 فراخوانی میشوند
http://i50.tinypic.com/nejjaq.jpg

مهدی فرزاد
شنبه 27 خرداد 1391, 09:54 صبح
سلام
اگر در تالار WPF این سئوال مطرح نمیشد جواب شما فقط ساختن یک کلاس با Property های Static بود!!
اما برای اینکه اینجا تالار WPF هست و حتما ما نیاز به Bind کردن اطلاعات داریم پس جواب شما به شکل زیر هست

شما نیاز به دو کلاس دارید
کلاس اول فیلد ها و پراپرتی های مورد نیاز شما رو برای دسترسی در سایر فرم ها میسازه و برای اینکه عمل Bind و انعکاس سریع تغییرات بر روی برنامه شما اعمال بشه این کلاس باید از INotifyPropertyChanged
مشتق بشه

من در زیر یک کلاس برای نگهداری نام و نام خانوادگی ایجاد کردم

class ParameterFilds : INotifyPropertyChanged
{

#region Fields (2)

private string _fname;
private string _lname;

#endregion Fields

#region Properties (2)


public string FName
{
get { return _fname; }
set
{
if (_fname == value) return;
_fname = value;
raisePropertyChanged("FName");
}
}

public string LName
{
get { return _lname; }
set
{
if (_lname == value) return;
_lname = value;
raisePropertyChanged("Lname");
}
}




#endregion Properties

#region INotifyPropertyChanged Members
/// <summary>
/// PropertyChanged notification.
/// </summary>
public event PropertyChangedEventHandler PropertyChanged;
void raisePropertyChanged(string propertyName)
{
var handler = PropertyChanged;
if (handler == null) return;
handler(this, new PropertyChangedEventArgs(propertyName));
}
#endregion
}


حالا نیاز به یک کلاس دارم تا یک نمونه از کلاس بالا رو برای من به صورت استاتیک و قابل دسترسی در تمام فرم ها در اختیار بگذاره

class ParameterClass
{
private static ParameterFilds _parameter = new ParameterFilds();
public static ParameterFilds Parameters { get { return _parameter; } set { _parameter = value; } }
}


حالا میتونم به جرات بگم کار تمام شد فقط کافیه هر جا نیاز داشتی کلاس بالا رو به شکل زیر Bind کنی

...
xmlns:local="clr-namespace:WpfApplication1"
...

<Grid>
<Grid.DataContext>
<local:ParameterClass/>
</Grid.DataContext>
<TextBox Text="{Binding Parameters.FName, Mode=TwoWay}" />
<TextBox Text="{Binding Parameters.LName, Mode=TwoWay}"/>


یا اینکه بدون Bind کردن هر جا خواستی بنویس

ParameterClass.Parameters.FName = ......;
ParameterClass.Parameters.LName = ......;


و هر جا خواستی فرا خونی کنی مثلا بنویس

MessageBox.Show(ParameterClass.Parameters.FName);


شما میتونید در کلاس دوم هر کالکشنی رو خواستید هم بجای این کار ایجاد کنید
یک مثال ضمیمه میکنم حتما ببینید

hamed jalili
شنبه 27 خرداد 1391, 11:38 صبح
مهدی جان ، خیلی ممنون به خاطر جواب کامل و دقیقی که دادی.

تا قبل از اینکه شما این جواب رو بفرستید من کلی دنبال راه حل گشتم ، راه های زیادی ( چه بهینه چه غیر بهینه ) پیدا کردم ولی روشی که در MSDN بود از همه روش هایی که قبل از جواب شما به این پست پیدا کرده بودم ، برام جالب تر بود .

روش بیان شده در MSDN :
http://msdn.microsoft.com/en-us/library/aa348545.aspx

هدف من از انجام این کار اینه : یک جدول هش و یک ObservableCollection دارم که یک سری آیتم را نگه می دارند این آیتم ها در قسمت های مختلف برنامه امکان تغییر ، اضافه و حذف شدن دارن . مثلا بخشی از آیتم ها در یک DataGrid نمایش داده می شوند و بخش دیگری در عملیات محاسباتی استفاده می شوند . برای این کار کل داده های مورد نیاز رو در داخل یک کلاس تعریف کردم و بعد در Startup Window یک Instance ی از این کلاس گرفتم و با استفاده از Application-Scope properties در تمامی بخش های برنامه به این داده ها دسترسی پیدا کردم .

روشی که شما توضیح دادین خیلی شبیه روش MSDN ه با این تفاوت که در روش بیان شده در MSDN کنترل Event رو من ندیدم ، من الان دارم در برنامه ام از روش MSDN استفاده می کنم و فعلا مشکلی پیش نیامده ( امیدوارم که اصلا پیش نیاد )
البته متوجه هستم که منظور اصلی شما ار روش بیان کردتون ، استفاده از مزیت Bind کردن هست ، ولی من در برنامه ام زیاد نیازی به Bind کردن این اطلاعات ندارم ، فقط برای یک DataGrid نیاز دارم به Bind کردن که اون رو هم به صورت زیر حل کردم :

DataGrid.ItemsSource = (Application.Current.Properties["Data Resource"] as Data_Resource).Defined_Lists;
Defined_Lists یک ObservableCollection است .

ولی یک سوال برام پیش آمد :
در روش شما ، مثلا String به صورت String ذخیره میشه و به همین شکل هم در دسترس هست ، ولی در روش MSDN ، یک String به Object تبدیل میشه که در هنگام استفاده نیاز هست که دوباره به String ، تبدیل بشه ( با استفاده از Cast و یا Convert )
سوال من اینه : یک جدول هش خیلی بزرگ به صورت Object در دسترس هست ، از آنجایی که در هر بار استفاده کردن باید به یک جدول هش Cast بشه ، آیا این عمل Cast هزینه بردار هست ؟ آیا وقتی که این جدول هش Cast میشود یک Instance از آن گرفته میشود ؟ ( به خاطر استفاده از RAM میپرسم - چون جدول خیلی بزرگی است هر بار Instance گرفتن و ذخیره در RAM نمی تواند بهینه باشد )


ممنون

مهدی فرزاد
دوشنبه 29 خرداد 1391, 10:52 صبح
سلام
این مورد رو من نمیدونم که چی میزان روی حافظه تاثیر میگذاره