 |
|
Code (C#)
ผมพยายามจะเปลี่ยนโค้ดนี้ให้เป็น MVVM Pattern อยู่หลายวันครับ เจอปัญหาเยอะแยะเลยครับ
ผมอยากจะแยกส่วนของ coding ออกจาก UI ครับ ช่วยด้วยครับ แนะนำให้ผมบรรลุทีนะครับ จะทำยังไงให้ โค้ดพวกนี้ ไปอยู่ ใน viewmodel ให้หมดเลย แล้ว biding ผ่าน datacontext ใน view แทนเอา
View ต้องมีโค้ดเท่านี้ ส่วนโค้ดอื่นๆต้องไปอยู้ใน ViewModel ให้หมดอะ มันถึงจะเป็น mvvm ช่วนแนะนำหน่อยนะครับบบบ ขอบคุณมากครับ
Code (C#)
public MasterView()
{
InitializeComponent();
this.DataContext = new MainViewModel();
}
*******โค้ดที่ติดปัญหาาาาา ยังไม่MVVM************
Code (C#)
public partial class MasterView : UserControl
{
//โค้ดที่ติดปัญหา ตามนี้ครับ ><
private double initMouseX;
private double finalMouseX;
private double x;
double mspWidth;
private double newx;
private DispatcherTimer timer;
private DoubleAnimationUsingKeyFrames anim;
public MasterView()
{
InitializeComponent();
this.DataContext = new MainViewModel();
timer = new DispatcherTimer();
anim = new DoubleAnimationUsingKeyFrames();
anim.Duration = TimeSpan.FromMilliseconds(1800);
timer.Interval = new TimeSpan(0, 0, 0, 0, 1000);
timer.Tick += new EventHandler(Tick);
}
void Tick(object sender, EventArgs e) // <= event นี้ ผมก็ สร้างไม่ได้ซะที
{
mspWidth = MetroStackPanel.ActualWidth;
if (newx > 100)
{
ClearKeyFrames();
}
else if ((newx + mspWidth) < 400)
{
double widthX = 400 - (newx + mspWidth);
double shiftX = newx + widthX;
ClearKeyFrames();
}
timer.Stop();
}
private void MainCanvasMouseLeftButtonUp(object sender, MouseButtonEventArgs e)// event นี้ผมทำได้ละครับ
{
finalMouseX = e.GetPosition(MainCanvas).X;
double diff = Math.Abs(finalMouseX - initMouseX);
if (diff > 5)
{
if (finalMouseX < initMouseX)
{
newx = x - (diff * 1.5);
}
else if (finalMouseX > initMouseX)
{
newx = x + (diff * 1.5);
}
anim.KeyFrames.Add(new SplineDoubleKeyFrame(newx,// บรรทัดนี้ผมจะ new SplineDoubleKeyFrame ยังไงอะ
KeyTime.FromTimeSpan(TimeSpan.FromSeconds(1)),
new KeySpline(0.161, 0.079, 0.008, 0.161)));
anim.FillBehavior = FillBehavior.HoldEnd;
MetroStackPanel.BeginAnimation(Canvas.LeftProperty, anim); // บบรทัดนี้ สุดยอดครับ ผมตันครับ จะ bidingยังไงไห้ MetroStackPanel ใน view สามารถเรียกใช้ได้
anim.KeyFrames.Clear();
timer.Start();
}
}
private void MainCanvasMouseLeftButtonDown(object sender, MouseButtonEventArgs e) // event นี้ก็ได้แล้วครับ
{
initMouseX = e.GetPosition(MainCanvas).X; //<== อันนี้ผมทำได้ละครับ biding ผ่าน ทาง CallMethodAction
x = Canvas.GetLeft(MetroStackPanel); // <== ตรงนี้ผมจะ biding ยังไงให้มันไป หา Control ที่ชื่อ MetroStackPanel ใน View อะครับมันไม่มี Event ให้ biding เหมือนกับ MainCanvas
}
private void MetrostackPanelMouseUp(object sender, MouseButtonEventArgs e)
{
}
private void ClearKeyFrames() // method นี้ก็เช่นกันครับผมไม่รู้จะ ส่ง keyframe ให้กับ MetroStackPanel วิธีใหน
{
anim.KeyFrames.Add(new SplineDoubleKeyFrame(4, KeyTime.FromTimeSpan(TimeSpan.FromSeconds(1)), new KeySpline(0.161, 0.079, 0.008, 1)));
anim.FillBehavior = FillBehavior.HoldEnd;
MetroStackPanel.BeginAnimation(Canvas.LeftProperty, anim);
anim.KeyFrames.Clear();
}
}
*********เป็น MVVM แล้ว ได้แค่นี้อะโฮกกกกกก***********
View
Code (C#)
/*MasterView.xaml
<Canvas ClipToBounds="True"
Background="#00000001"
x:Name="MainCanvas">
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseLeftButtonUp"
SourceObject="{Binding ElementName=MainCanvas}">
<ic:CallMethodAction MethodName="OnMainCanvas"
TargetObject="{Binding Path=DataContext,ElementName=MainCanvas}" />
</i:EventTrigger>
</i:Interaction.Triggers>
<StackPanel Canvas.Left="20"
x:Name="MetroStackPanel"
Canvas.Top="12">
</StackPanel>
</Canvas>*/
Dependency Base
Code (C#)
public class DependencyObjectViewModel : DependencyObject
{
public static readonly DependencyProperty MainCanvasProperty =
DependencyProperty.Register("MainCanvas", typeof(string), typeof(DependencyObjectViewModel), new UIPropertyMetadata(null));
}
ViewModel
Code (C#)
public class MainViewModel : DependencyObjectViewModel
{
#region Data
private ICommand runCommand;
private ICommand shouldFailCommand;
private Boolean shouldFail = false;
private ThreadableItemViewModel<List<PropertyDataBase>> threadVM =
new ThreadableItemViewModel<List<PropertyDataBase>>();
#endregion
#region Constructor
public MainViewModel()
{
Run();
}
#endregion
private void Run()
{
int i = 0;
Func<Dictionary<String, Object>, ThreadableItem<List<PropertyDataBase>>> taskFunc = (inputParams) =>
{
try
{
#region TEST EXAMPLE CODE, YOU SHOULD NOT DO THIS IN PRODUCTION CODE
if (ShouldFail)// thread error
{
throw new InvalidOperationException(
"InvalidOperationException occurred\r\n\r\n" +
"This Exception has been raised inside the Window1ViewModel delegate " +
"which is the actual payload for the ThreadableItemViewModel<T> TaskFunc delegate.\r\n\r\n" +
"Which is obvioulsy not what you would do in a production system.\r\n\r\n" +
"You would more typically catch your own business Exceptions " +
"(say from talking to WCF) and then rethrow them. " +
"This just demomstrated how all this hangs together");
}
else
{
List<PropertyDataBase> data = new List<PropertyDataBase>();
GlobalModel.GlobalMetrolClick = true;
if (GlobalModel.GlobalMetrolClick)
{
ThreadModel dm = new ThreadModel();
dm.ConnectModel();
var ServiceNotOffJob = from ser in dm.ServiceModel
join cus in dm.CustomerModel on ser.cusID equals cus.cusID
where cus.cusID.Equals("M000000001") &&
ser.IsServices.Equals("3")
select new PropertyDataBase
{
CustomerID = cus.cusID,
ServiceID = ser.serID
};
if (ServiceNotOffJob.Count() > 0)
{
i = (Int32)inputParams["loopMax"];
foreach (var item in ServiceNotOffJob)
{
data.Add(new PropertyDataBase()
{
CustomerID = item.CustomerID,
ServiceID = item.ServiceID
});
i++;
}
}
}
return new ThreadableItem<List<PropertyDataBase>>(data, String.Empty);
}
#endregion
}
catch (Exception ex)
{
return new ThreadableItem<List<PropertyDataBase>>(null, ex.Message);
}
};
threadVM.TaskFunc = taskFunc;
Dictionary<String, Object> parameters = new Dictionary<String, Object>();
parameters.Add("loopMax", i);
threadVM.Parameters = parameters;
runCommand = new SimpleCommand // Run
{
CanExecuteDelegate = x => !threadVM.IsBusy,
ExecuteDelegate = x => { threadVM.Run(); }
};
shouldFailCommand = new SimpleCommand // Test Fail
{
CanExecuteDelegate = x => !threadVM.IsBusy,
ExecuteDelegate = x => { ShouldFail = !ShouldFail; }
};
}
public ThreadableItemViewModel<List<PropertyDataBase>> ThreadVM // Property ThreadVM
{
get { return threadVM; }
}
public ICommand RunCommand
{
get { return runCommand; }
}
public ICommand ShouldFailCommand
{
get { return shouldFailCommand; }
}
public bool ShouldFail // Property ShouldFail
{
get { return shouldFail; }
set
{
shouldFail = value;
//base.OnPropertyChanged("ShouldFail");
}
}
//ผมทำได้เท่านี้ครับ
private double initMouseX;
private double finalMouseX;
private double x;
double mspWidth;
private double newx;
private DispatcherTimer timer;
private DoubleAnimationUsingKeyFrames anim;
public LoginView MainCanvas //ผม Biding ผ่าน Property นี้ครับ เอา Position mouse จาก MainCanvas ใน view ง่ะๆๆ
{
get { return (LoginView)GetValue(MainCanvasProperty); }
set { SetValue(MainCanvasProperty, value);}
}
public LoginView MetroStackPanel
{
get { return (LoginView)GetValue(MetroStackPanelProperty); }
set { SetValue(MetroStackPanelProperty, value); }
}
public void OnMainCanvas(object sener, MouseButtonEventArgs e)
{
initMouseX = e.GetPosition(MainCanvas).X; // ได้ position mouse มาแล้วครับ
x = Canvas.GetLeft(MetroStackPanel);// <<< error ครับ ไม่รู้จะ biding ยังไง ใน view MetroStackPanel มันเป็นชื่อ ของ Control Canvas อะครับ มึนครับ จะอ้างตำแหน่ง Canvas.GetLeft ของ Canvas ใน View ได้ยังไง
MessageBox.Show(x.ToString());
}
}
Tag : .NET, LINQ, C#, VS 2010 (.NET 4.x)
|
ประวัติการแก้ไข 2012-04-04 02:59:53 2012-04-04 03:00:57 2012-04-04 03:05:51 2012-04-04 03:18:56 2012-04-04 03:20:20 2012-04-04 03:22:06 2012-04-04 03:24:35 2012-04-04 03:38:38 2012-04-04 03:43:02 2012-04-04 03:50:09 2012-04-04 03:58:08 2012-04-04 04:05:25 2012-04-04 04:06:04 2012-04-04 04:06:05 2012-04-04 04:07:58 2012-04-04 04:08:52 2012-04-04 04:09:53 2012-04-04 04:10:39 2012-04-04 04:23:53 2012-04-04 04:25:15
|
 |
 |
 |
 |
Date :
2012-04-04 02:58:35 |
By :
Drewsn32 |
View :
2799 |
Reply :
1 |
|
 |
 |
 |
 |
|
|
|
 |