PDA

View Full Version : MVVM , Refresh ImageSource Binding ?



idxxbi
شنبه 20 فروردین 1390, 12:50 عصر
سلام
یه جدول دارم ( state , pic1 , pic2 ) (مدل)
یه دکمه ( ویو )
میخوام بکگراند دکمه بر اساس مقدار state بشه pic1 یا pic2 و با تغییر state بکگراند عوض بشه.
کاری که کردم :

<Button CommandParameter="{Binding}" Command="{Binding DataContext.ChangeStateCommand, RelativeSource={RelativeSource AncestorType={x:Type ListBox}, Mode=FindAncestor}}">
<Button.Background>
<ImageBrush ImageSource="{Binding Pic, Converter={StaticResource imageConverter}}"/>

</Button.Background>
</Button>

مدل :

public partial class ُStates
{
public string Pic
{
get
{
if (state == 0)
return pic1;
else
return pic2;
}
}
}

و ,ویومدل :

public ListCollectionView Statess
{
get { return _states; }
set
{
_states= value;
RaisePropertyChanged("Statess");
}
}

public ICommand ChangeStateCommand
{
get
{
return new RelayCommand<States>(ChangeStateExecute);
}
}
void ChangeStateExecute<T>(T o)
{
(o as States).state = (o as States).state.Value == 0 ? (byte)1 : (byte)0;
StatesDataStoreService.Update((o as States));
StatesDataStoreService.Save();
//
}


چیکار کنم که با تغییر state بکگراند هم تغییر کنه ؟

با تشکر

farashah_jalal
یک شنبه 21 فروردین 1390, 07:49 صبح
با سلام
شما مي توني توي قسمت view يه button بزاري و command اون رو binding كني با view model در view modelيك proprty بسازي از نوع string و اون تصويري كه مي خواي با اون binding انجام بشه رو بهش مقدار بدي
و براي تصوير يه كنترل image بزار داخل background اون buttonو source اون image رو بايند كن با property در view model ساختي و ادرس اون عكس رو بهش دادي نسبت بدي.
بايد توجه داشته باشي كه در بايند كردن تصوير بايد اين تنظيمات رو هم انجام بدي mode=twowayباشه و update triger=onproppertychange

Amir Oveisi
یک شنبه 28 فروردین 1390, 14:33 عصر
پاسخ قبلیم اشتباه بود، لطفا به پست شماره 9 مراجعه کنید. :)

davoodrm666_666
پنج شنبه 01 اردیبهشت 1390, 19:37 عصر
6899368993سلام
من یک نمونه برنامه نوشتم که می خوام یک عکس رو انتخاب کنم عکس انتخابی در ViewModel در View نمایش داده نمی شه کلا هر تغییری در ViewModel انجام میدم در View اعمال نمی شه لازم به ذکر که از ObservableCollection نمی خوام استفاده کنم چون فقط یک رکورد در این View وارد می شه لطفا راهنمایی کنید

Amir Oveisi
پنج شنبه 01 اردیبهشت 1390, 20:38 عصر
لطفا به پست شماره 9 مراجعه کنید. :)

farashah_jalal
جمعه 02 اردیبهشت 1390, 00:16 صبح
با سلام
اگه عکس رو خارج از grid قرار بدی مشکلت حل می شه. چون در داخل گرید DataContex مقدار دهی شده و اولویت با grid است که مقدار دهی شده است.
و من پیشنهاد می کنم datacontex فرم main رو در app.xamlمقدار دهی کنی.
این پروژه می تونه نمونه خوبی در این مورد باشه.
موفق باشید.

68998

davoodrm666_666
شنبه 03 اردیبهشت 1390, 07:41 صبح
پیشنهاد می کنم از RelayCommand استفاده کنید. در اینصورت همونطور که در پست قبلی توضیح دادم با استفاده از متد OnPropertyChanged، میتونید تغییر مقدار یک property رو در ViewModel به View اطلاع بدید.

ممنون كه جواب داديد اما من از ReplayCommand استفاده كردم درضمن ReplayCommand ارتباطي به اين قضيه نداره و براي Bind كردن Event به كنترل ها استفاه مي شود كه در كد من به درستي داره كار ميكنه


با سلام
اگه عکس رو خارج از grid قرار بدی مشکلت حل می شه. چون در داخل گرید DataContex مقدار دهی شده و اولویت با grid است که مقدار دهی شده است.
و من پیشنهاد می کنم datacontex فرم main رو در app.xamlمقدار دهی کنی.
این پروژه می تونه نمونه خوبی در این مورد باشه.
موفق باشید.

68998

دوست عزيز فقط عكس نيست بلكه Button جديد هم مقادير Entity كه View بايند شده رو Refresh نمي كنه

farashah_jalal
شنبه 03 اردیبهشت 1390, 08:31 صبح
دوست عزيز فقط عكس نيست بلكه Button جديد هم مقادير Entity كه View بايند شده رو Refresh نمي كنه
چون grid شما مقدار datacontex داره اگه Button را خارج از grid هم قرار بدي مشكلت حل ميشه .
كدي كه در ضميمه پست قبلي قرار دادم نگاه كن.

Amir Oveisi
شنبه 03 اردیبهشت 1390, 10:22 صبح
درضمن ReplayCommand ارتباطي به اين قضيه نداره و براي Bind كردن Event به كنترل ها استفاه مي شود
کاری به event ها نداره و با command ها کار میکنه. درسته اون متد ربطی به relaycommand نداره و من اشتباه عرض کردم خدمتتون.
یکی از کارهایی که در معماری mvvm باید انجام بشه انتقال تغییرات مقادیر bind شده از viewmodel به model هست. این اتفاق در بعضی شرایط به صورت خودکار انجام نمیشه بنابراین باید برای رفع این مشکل خودتون اقدام کنید. خوشبختانه خود .net framework امکاناتی داره که میشه با استفاده از اون ها راحت تر این کار رو انجام داد.
شما میتونین یک کلاس پایه برای viewmodel داشته باشید به این شکل:
public abstract class ViewModelBase : INotifyPropertyChanged, IDisposable
{
protected ViewModelBase()
{
}

public event PropertyChangedEventHandler PropertyChanged;

protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = this.PropertyChanged;
if (handler != null)
{
var e = new PropertyChangedEventArgs(propertyName);
handler(this, e);
}
}

public void Dispose()
{
this.OnDispose();
}

protected virtual void OnDispose()
{
}
}

اینترقیس INotifyPropertyChanged این امکان رو به شما میده که ساختاری ایجاد کنید که بتونین تغییرات لایه viewmodel رو با استفاده از متد OnPropertyChanged به لایه view منتقل کنید. فقط کافیه که کلاس های viewmodel اتون از viewmodelbase ارث ببرن.
نمونه کامل استفاده از این روش برای پیاده سازی MVVM تو امضام هست میتونین یه نگاهی بهش بندازید ببینید کد کاملشو و نحوه ارتباط بین لایه ها با این روش که عرض کردم رو مشاهده کنید.

باز هم بابت پاسخ اشتباهم عذر میخوام :)

davoodrm666_666
یک شنبه 04 اردیبهشت 1390, 08:43 صبح
چون grid شما مقدار datacontex داره اگه Button را خارج از grid هم قرار بدي مشكلت حل ميشه .
كدي كه در ضميمه پست قبلي قرار دادم نگاه كن.

من كد شما رو نگاه كردم شما هم DataContext رو در Layout اصلي پر كرديد. درضمن كنترل هاي من بايد توي يك Layout قرار بگيرند و اگر از Grid خارج كنم خطا مي ده

farashah_jalal
یک شنبه 04 اردیبهشت 1390, 11:57 صبح
با سلام
اگه به كد توجه كرده باشي من كنترل هاي مثل button ها ي كه براي درج از اون استفاده مي شوند رو داخل يك stack panel قرار دادم .

<StackPanel FlowDirection="RightToLeft" Margin="324,125,16,0" Orientation="Horizontal" Height="37" VerticalAlignment="Top">
<Button Width="30" Height="30" Command="{Binding NewCommand}" Name="BtnNew" Tag="..\ResourceImage\new.png" Style="{StaticResource imageButtons}" ToolTip="اضافه نمودن" TabIndex="8" />
<Button Width="30" Height="30" Command="{Binding InsertCommand}" Name="BtnAdd" Tag="..\ResourceImage\en_Add.png" Style="{StaticResource imageButtons}" ToolTip="اضافه نمودن" TabIndex="8" />
<Button Width="30" Height="30" Command="{Binding UpdateCommand}" Name="BtnEdit" Tag="..\ResourceImage\en_Edit.png" Style="{StaticResource imageButtons}" ToolTip="ويرايش نمودن" />
<Button Width="30" Height="30" Command="{Binding DeleteCommand}" Name="BtnDel" Tag="..\ResourceImage\Symbols-Delete-32x32.png" Style="{StaticResource imageButtons}" ToolTip="حذف کردن" />
</StackPanel>



و فقط كد هاي مربوط به كنترل ها مانند text box هاي روي فرم رو داخل يك grid قرار دادم و به datacontex اون مقدار دادم

<Grid Height="283" DataContext="{Binding NewUser}" HorizontalAlignment="Left" Margin="136,162,0,0" Name="grid1" VerticalAlignment="Top" Width="400">
<Grid.RowDefinitions>
<RowDefinition Height="124*" />
<RowDefinition Height="14*" />
<RowDefinition Height="145*" />
</Grid.RowDefinitions>
<TextBox SelectedText="" Text="{Binding Path=ID, Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" Height="28" HorizontalAlignment="Right" Margin="0,13,117,0" Name="txtcode" VerticalAlignment="Top" Width="52" TabIndex="0" />
<TextBox Height="30" Text="{Binding Path=FullName, Mode=TwoWay}" HorizontalAlignment="Right" Margin="0,49,117,0" Name="textBox1" VerticalAlignment="Top" Width="129" InputLanguageManager.InputLanguage="fa-ir" TabIndex="1" />
<TextBox Height="30" Text="{Binding Path=UserName, Mode=OneWayToSource}" HorizontalAlignment="Right" Margin="0,85,117,0" Name="textBox2" VerticalAlignment="Top" Width="129" InputLanguageManager.InputLanguage="en-us" TabIndex="2" />
<TextBox Height="30" Text="{Binding Path=Phon,Mode=OneWayToSource}" HorizontalAlignment="Right" Margin="0,123,117,0" Name="textBox3" VerticalAlignment="Top" Width="129" TabIndex="3" Grid.RowSpan="3" />
<Label Content=":نام و نام خانوادگي" Height="28" HorizontalAlignment="Right" Margin="0,50,14,0" Name="label1" VerticalAlignment="Top" />
<Label Content=":نام کاربري" Height="31" HorizontalAlignment="Right" Margin="0,84,14,0" Name="label2" VerticalAlignment="Top" />
<Label Content=":تلفن" Height="28" HorizontalAlignment="Right" Margin="0,0,20,0" Name="label3" VerticalAlignment="Top" Grid.RowSpan="2" Grid.Row="1" />
<Label Content=":موبايل" HorizontalAlignment="Right" Margin="0,26,20,0" Name="label4" Height="30" VerticalAlignment="Top" Grid.Row="2" />
<Label Content="کد" Height="28" HorizontalAlignment="Right" Margin="0,5,20,0" Name="label8" VerticalAlignment="Top" />
<TextBox Height="30" Text="{Binding Path=Mobile,Mode=OneWayToSource}" HorizontalAlignment="Right" Margin="0,21,117,0" Name="textBox4" VerticalAlignment="Top" Width="129" TabIndex="4" Grid.Row="2" />
<Label Content=":پست الکترونيک" Height="28" HorizontalAlignment="Right" Margin="0,59,14,0" Name="label7" VerticalAlignment="Top" Grid.Row="2" />
<TextBox Height="30" Text="{Binding Path=Mail,Mode=OneWayToSource}" HorizontalAlignment="Right" Margin="0,57,117,0" Name="textBox7" VerticalAlignment="Top" Width="238" TabIndex="5" Grid.Row="2" />
<Label Content="آدرس" Height="28" HorizontalAlignment="Right" Margin="0,93,17,0" Name="label6" VerticalAlignment="Top" Grid.Row="2" />
<TextBox InputLanguageManager.InputLanguage="fa-ir" Text="{Binding Path=Adress,Mode=OneWayToSource}" Height="49" HorizontalAlignment="Right" Margin="0,93,117,0" Name="textBox6" VerticalAlignment="Top" Width="277" TextWrapping="Wrap" TabIndex="6" Grid.Row="2" />
</Grid>


و data contex مربوط به فرمم رو در داخل محيط كد نويسي app.xaml .csبه اون مقدار دادم كه كد اون به اين صورت مي باشد.


protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);

MainWindow window = new MainWindow();
var viewModel = new MainWindowViewModel();
window.DataContext = viewModel;
window.Show();
}


موفق باشيد.

davoodrm666_666
دوشنبه 05 اردیبهشت 1390, 07:23 صبح
مشكل Refresh شدن همه كنترل ها با كلاس ViewModelBase حل شد بجز عكس كه از نوع Binary هست و در مثال ها همه آدرس تصوير رو در ديتابيس ذخيره مي كنند نه خود عكس رو .