'WP7'에 해당되는 글 88건

  1. 2011.12.02 [wp7] 윈폰7 앱 메모리사용량 참조
  2. 2011.11.24 [wp7] WP7 ToolKit TimePicker 12시간제/24시간제 강제로 바꾸기
  3. 2011.11.24 [wp7] Custom DatePicker 만들기 For Toolkit
  4. 2011.11.24 [wp7] Debug, Release 외에 디버깅 모드 추가 하기
  5. 2011.11.23 [wp7] "The application could not be launched for debugging" 에뮬레이터에서 이런 에러가 나올때
  6. 2011.11.23 [wp7] 마켓에 올릴때 에러 "The [NeutralResourceLanguage] attribute is missing on the entry assembly"
  7. 2011.11.21 [wp7] 하위 UserControl의 Parent(부모) 컨트롤 메소드 호출 하기
  8. 2011.11.16 [wp7] 윈폰에서 CSV 처리
  9. 2011.11.16 [wp7] foreach 문 처음이나 끝 부분을 Skip 하고 싶을때.
  10. 2011.11.11 [wp7] WCF Rest 에서 Cookie값 받아오기(WCF Login Server Session) 1
  11. 2011.11.08 [wp7] EUC-KR을 윈폰7에서 사용하기 5
  12. 2011.10.19 [Portfolio] Window Phone 7 App "Fortune Coins" (Hugeflow, 2011.01 ~ 2011.05)
  13. 2011.10.19 [Portfolio] Window Phone 7 App "Look n Type" (Hugeflow, 2010.09 ~2010.12)
  14. 2011.10.19 [Portfolio] Windows Phone7 App "ToolBox" (Silverlight,C#,wp7,휴즈플로우) 2010.9 ~ 2010.12
  15. 2011.05.27 [WP7] Toast Notification 만드는법 4 (Mango Ver)
  16. 2011.05.27 [WP7] Toast Notification 만드는법 3 (Mango Ver)
  17. 2011.05.27 [wp7] Toast Notification 만드는법 2 (Mango Ver) 1
  18. 2011.05.17 [WCF] WCF REST service project 만드는법
  19. 2011.05.03 [wp7] Customizing WP7 Push Notification Tiles
  20. 2011.04.26 [wp7] 모바일 앱에 광고 탑재하는법 2
  21. 2011.04.25 [wp7] 폰에서 유니크한 ID 만들기
  22. 2011.04.22 [wp7] 자기가 사용하는 기계 Model명을 얻고 싶을때
  23. 2011.03.31 [wp7] MVVM에서의 Invalid cross-thread access.메세지
  24. 2011.03.31 [wp7] Command를 Behind에서 사용하자
  25. 2011.03.25 [wp7] 윈도우 폰 캡쳐 프로그램
  26. 2011.03.24 [wp7] 어셈블리로부터 버전 정보 받아오기
  27. 2011.03.24 [WP7] 페이지 이동간의 파라미터 주기
  28. 2011.03.21 [wp7] Control 만들기
  29. 2011.03.21 [wp7] Control 만들때 generic.xaml 에서 Converter 쓰기
  30. 2011.03.21 [wp7] WebClient에서 Caching 문제로 갱신이 되지 않을 때…
Windows Phone 72011. 12. 2. 15:47

Microsoft.Phone.dll에 포함되어 있는 Microsoft.Phone.Info.DeviceExtendedProperties 클래스를 통해
 
long totalBytes = (long)Microsoft.Phone.Info.DeviceExtendedProperties.GetValue(“DeviceTotalMemory”);
 
이런 식으로 얻을 수 있습니다.
 
GetValue에 parameter로 전달할 수 있는 이름은 아래와 같습니다.
 
DeviceTotalMemory – 윈도우폰 전체 메모리
ApplicationCurrentMemoryUsage – 앱의 현재 메모리 사용량
ApplicationPeakMemoryUsage – 앱의 최고 메모리 사용량
 
 
메모리 사용량을 간단히 표시할 수 있는 MemoryUsageBox 컨트롤
 
이것을 간단하게 사용들 하시라고 오늘 HugeFlow.Phone 라이브러리에
메모리 사용량을 표시해주는 컨트롤을 추가하였습니다.
이름하야 MemoryUsageBox란 컨트롤입니다.
 
일반적으로는 메모리 사용량을 보고 싶은 페이지에 아래와 같은 형태로 추가하시면 끝.
 
// Constructor
public DetailsPage()
{
    InitializeComponent();
 
#if DEBUG
    LayoutRoot.Children.Add(new MemoryUsageBox());
#endif
}

Posted by 동동(이재동)
Windows Phone 72011. 11. 24. 21:01

코레일 시간은 무조건 24시간제이다 즉 오전오후를 쓰지 않고 24시간제로 쓴다.

물론 셀렉트에서는 12시간제로 하고 결과물은 24시간제로 뺼수 있다.

하지만 사용자가 12시간제이면 불편할것이다. 오후 3시를 골랐는데 15시로 나오면 좀 이상.

그래서 Toolkit의 TimerPicker에서 강제로 24시간으로 바꿀려고 노력했지만 잘안되었다.

어렵게 알았는데 시스템 설정에서 24시간 12시간제를 설정할 수가 있었고

설정대로 Picker가 알아서 바꼈다.

강제로 할려면

http://silverlight.codeplex.com/workitem/7190

여기를 참고 해서 그대로 하면 되는데 아직 해보지는 않았다 나중에 문제 생기면 해봐야지

Posted by 동동(이재동)
Windows Phone 72011. 11. 24. 16:53

예전에 했는데도 불구하고 이번에 또 하느라 삽질을 하였다.

그래서 이렇게 포스팅 한다.

먼저 Toolkit을 설치하고 소스를 받는다.

현재 무한대로 나오는 년도를 2050년까지만 나오게 하자. 년도만 나오게도 할수 있다.

 

이미지 2

 

일단 복사해야할 파일은

DataSource.cs

DatePicker.cs(필요에 따라 없어도 됨)

DateTimePickerPageBase.cs

Common 폴더에 Tuple.cs

DatePickerPage.xaml

이렇게 복사한다

DatePickerPage.xaml은 UI 에 쓰이기 때문에 이름을 바꾼다.

namespace는 그냥 가만히 나두는게 좋다

만약에 저위에 처럼 년도만 보이게 하고 싶으면

DatePickerPage.xaml.cs 에서

public partial class CustomYearDatePicker : DateTimePickerPageBase
    {
        LoopingSelector lsMonth;
        LoopingSelector lsDay;

        /// <summary>
        /// CustomYearDatePicker Constructor
        /// </summary>
        public CustomYearDatePicker()
        {
            InitializeComponent();

            // Hook up the data sources
            PrimarySelector.DataSource = new YearDataSource();
            //SecondarySelector.DataSource = new MonthDataSource();
            //TertiarySelector.DataSource = new DayDataSource();

            //가짜 데이터 넣기
            lsMonth = new LoopingSelector();
            lsMonth.DataSource = new MonthDataSource();

            lsDay = new LoopingSelector();
            lsDay.DataSource = new MonthDataSource();

            InitializeDateTimePickerPage(PrimarySelector, lsMonth, lsDay);
        }

        /// <summary>
        /// Gets a sequence of LoopingSelector parts ordered according to culture string for date/time formatting.
        /// </summary>
        /// <returns>LoopingSelectors ordered thffby culture-specific priority.</returns>
        protected override IEnumerable<LoopingSelector> GetSelectorsOrderedByCulturePattern()
        {
            return GetSelectorsOrderedByCulturePattern(
                CultureInfo.CurrentCulture.DateTimeFormat.ShortDatePattern.ToUpperInvariant(),
                new char[] { 'Y', 'M', 'D' },
                //new LoopingSelector[] { PrimarySelector, SecondarySelector, TertiarySelector });
                new LoopingSelector[] { PrimarySelector, lsMonth, lsDay });
        }

 

이런식으로 바꿔준다. 가짜 데이터를 넣고 Xaml(UI)딴에서는 삭제 한다.

그리고 2050년까지만 보이게 하기 위해서

DataSource.cs를 이렇게 바꾸어 준다.

class YearDataSource : DataSource
   
{
        protected override DateTime? GetRelativeTo(DateTime relativeDate, int delta)
        {
            if ((1601 == relativeDate.Year) || (3000 == relativeDate.Year))
            //if ((2010 == relativeDate.Year) || (2051 == relativeDate.Year))
           
{
                return null;
            }

            int nextYear = relativeDate.Year + delta;

            if (nextYear < 2010)
            {
                nextYear = 2051 + (nextYear - 2010);
            }
            else if (nextYear > 2050)
            {
                nextYear = 2009 + (nextYear - 2050);
            }


            //int nextYear = relativeDate.Year + delta;
           
int nextDay = Math.Min(relativeDate.Day, DateTime.DaysInMonth(nextYear, relativeDate.Month));
            return new DateTime(nextYear, relativeDate.Month, nextDay, relativeDate.Hour, relativeDate.Minute, relativeDate.Second);
        }
    }

혹시나 모르니 DatePicker.xaml을 올려둔다.

<Primitives:DateTimePickerPageBase
    x:Class="Microsoft.Phone.Controls.CustomDatePicker"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
    xmlns:Primitives="clr-namespace:Microsoft.Phone.Controls.Primitives;assembly=Microsoft.Phone.Controls.Toolkit" 
    xmlns:Controls="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone.Controls.Toolkit" FontFamily="{StaticResource PhoneFontFamilyNormal}"
    FontSize="{StaticResource PhoneFontSizeNormal}"
    Foreground="{StaticResource PhoneForegroundBrush}"
    SupportedOrientations="PortraitOrLandscape" Orientation="Portrait"
    mc:Ignorable="d" d:DesignHeight="728" d:DesignWidth="480">

    <Primitives:DateTimePickerPageBase.Resources>
        <Controls:DateTimePickerResources x:Key="DateTimePickerResources"/>
        <ExponentialEase x:Key="Ease" EasingMode="EaseIn"/>
    </Primitives:DateTimePickerPageBase.Resources>

    <Grid Background="{StaticResource PhoneChromeBrush}">
        <VisualStateManager.VisualStateGroups>
            <VisualStateGroup x:Name="VisibilityStates">
                <VisualState x:Name="Open">
                    <Storyboard>
                        <DoubleAnimation
                            Storyboard.TargetName="PlaneProjection"
                            Storyboard.TargetProperty="RotationX"
                            From="-50"
                            To="0"
                            Duration="0:0:0.2"/>
                    </Storyboard>
                </VisualState>
                <VisualState x:Name="Closed">
                    <Storyboard>
                        <DoubleAnimation
                            Storyboard.TargetName="PlaneProjection"
                            Storyboard.TargetProperty="RotationX"
                            To="90"
                            Duration="0:0:0.2"
                            EasingFunction="{StaticResource Ease}"/>
                    </Storyboard>
                </VisualState>
            </VisualStateGroup>
        </VisualStateManager.VisualStateGroups>
        <Grid.Projection>
            <PlaneProjection x:Name="PlaneProjection"/>
        </Grid.Projection>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition/>
        </Grid.RowDefinitions>

        <!-- SystemTray placeholder -->
        <Rectangle
            x:Name="SystemTrayPlaceholder"
            Grid.Row="0"
            Height="32"/>
        <!-- Title -->
        <TextBlock
            Grid.Row="1"
            Text="{Binding DatePickerTitle, Source={StaticResource DateTimePickerResources}}"
            FontFamily="{StaticResource PhoneFontFamilySemiBold}"
            FontSize="{StaticResource PhoneFontSizeMedium}"
            Foreground="{StaticResource PhoneForegroundBrush}"
            Margin="24,16,12,24"/>
        <!-- LoopingSelectors -->
        <Grid
            Grid.Row="2"
            HorizontalAlignment="Center">
            <Grid.ColumnDefinitions>
                <ColumnDefinition/>
                <ColumnDefinition/>
                <ColumnDefinition/>
            </Grid.ColumnDefinitions>
            <Primitives:LoopingSelector
                x:Name="SecondarySelector"
                Grid.Column="0"
                Width="148"
                ItemSize="148,148"
                ItemMargin="6" >
                <Primitives:LoopingSelector.ItemTemplate>
                    <DataTemplate>
                        <StackPanel
                            HorizontalAlignment="Left"
                            VerticalAlignment="Bottom"
                            Margin="6">
                            <TextBlock
                                Text="{Binding MonthNumber}"
                                FontSize="54"
                                FontFamily="{StaticResource PhoneFontFamilySemiBold}"
                                Margin="0,-8"/>
                            <TextBlock
                                Text="{Binding MonthName}"
                                FontSize="20"
                                FontFamily="{StaticResource PhoneFontFamilyNormal}"
                                Foreground="{StaticResource PhoneSubtleBrush}"
                                Margin="0,-2"/>
                        </StackPanel>
                    </DataTemplate>
                </Primitives:LoopingSelector.ItemTemplate>
            </Primitives:LoopingSelector>
            <Primitives:LoopingSelector
                x:Name="TertiarySelector"
                Grid.Column="1"
                Width="148"
                ItemSize="148,148"
                ItemMargin="6">
                <Primitives:LoopingSelector.ItemTemplate>
                    <DataTemplate>
                        <StackPanel
                            HorizontalAlignment="Left"
                            VerticalAlignment="Bottom"
                            Margin="6">
                            <TextBlock
                                Text="{Binding DayNumber}"
                                FontSize="54"
                                FontFamily="{StaticResource PhoneFontFamilySemiBold}"
                                Margin="0,-8"/>
                            <TextBlock
                                Text="{Binding DayName}"
                                FontSize="20"
                                FontFamily="{StaticResource PhoneFontFamilyNormal}"
                                Foreground="{StaticResource PhoneSubtleBrush}"
                                Margin="0,-2"/>
                        </StackPanel>
                    </DataTemplate>
                </Primitives:LoopingSelector.ItemTemplate>
            </Primitives:LoopingSelector>
            <Primitives:LoopingSelector
                Grid.Column="1"
                x:Name="PrimarySelector"
                Width="148"
                ItemSize="148,148"
                ItemMargin="6">
                <Primitives:LoopingSelector.ItemTemplate>
                    <DataTemplate>
                        <StackPanel
                            HorizontalAlignment="Left"
                            VerticalAlignment="Bottom"
                            Margin="6">
                            <TextBlock
                                Text="{Binding YearNumber}"
                                FontSize="54"
                                FontFamily="{StaticResource PhoneFontFamilySemiBold}"
                                Margin="0,-8"/>
                            <TextBlock
                                Text=" "
                                FontSize="20"
                                FontFamily="{StaticResource PhoneFontFamilyNormal}"
                                Foreground="{StaticResource PhoneSubtleBrush}"
                                Margin="0,-2"/>
                        </StackPanel>
                    </DataTemplate>
                </Primitives:LoopingSelector.ItemTemplate>
            </Primitives:LoopingSelector>
        </Grid>
    </Grid>

    <Primitives:DateTimePickerPageBase.ApplicationBar>
        <shell:ApplicationBar IsVisible="True">
            <shell:ApplicationBarIconButton
                IconUri="/Toolkit.Content/ApplicationBar.Check.png"
                Text="DONE"/>
            <shell:ApplicationBarIconButton
                IconUri="/Toolkit.Content/ApplicationBar.Cancel.png"
                Text="CANCEL"/>
        </shell:ApplicationBar>
    </Primitives:DateTimePickerPageBase.ApplicationBar>

</Primitives:DateTimePickerPageBase>

그냥 xaml을 복사하면 에러가 날것이다.

2개는 꼭 이렇게 수정한다.

xmlns:Primitives="clr-namespace:Microsoft.Phone.Controls.Primitives;assembly=Microsoft.Phone.Controls.Toolkit" 
 xmlns:Controls="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone.Controls.Toolkit"
사용법은
 
<tk:DatePicker x:Name="TkDatePicker" PickerPageUri="/GloryApp;component/Controls/CustomDatePicker.xaml" />

알아내느라 힘들었고 출처 따윈 없다. 검색해도 안 나옴 toolkit 소스를 직접 분석해야 한다.
 
 
Posted by 동동(이재동)
Windows Phone 72011. 11. 24. 10:21

폰에 광고를 넣을 일이 있어서 광고 버전과 광고가 장착되지 않은 버전으로 결과물이 다르게 나오게 하고 싶었다.

Debug, Release

외에 DebugAD,RelaseAD 를 만들어서 빌드할때 옵션을 저렇게 주면 bin/ReleaseAD 폴더에 xap파일이 생성된다.

 

빌드에서 Configuration Manager을 클릭

image1

 

New를 클릭

이미지 4

 

Name을 설정하고 Setting을 Release 한다.디버그도 따로 만들어 놓는 것도 좋다.

이미지 5

 

설정이 되었으면 Configration에서 ReleaseAD를 설정하고

아래 symbols 에 AD 를 꼭! 집어 넣는다.(중요!)

그냥 표시니 다른걸로 바꿔도 된다.

 

이미지 8

자 이제 소스에서 차별점을 두어보자

#if !AD
            AdControl.Visibility = System.Windows.Visibility.Collapsed;
#endif

소스에 이런식으로 넣게 되면 AD가 아닐때 즉 보통 릴리즈모드일때는 광고가 보이지 않게 된다.

Posted by 동동(이재동)
Windows Phone 72011. 11. 23. 16:09

망고 7.0 에서 7.1로 컨버팅 하는 과정에서 실행을 해도 저런 에러가 날 때가  있다.

“The application could not be launched for debugging. Ensure that the target device screen is unlocked and that the application is installed”

풀 에러 메세지는 저렇다

그럼 어떻게 하느냐?

solution Properties에서(솔루션 오른쪽 버튼 클릭)

err

 

저렇게 해당 start Project에서 Deploy 부분이 체크가 안되 있을것이다.

Depoly 부분 체크를 다시 해놓으면 제대로 작동된다.

참고 : http://cisforcoder.wordpress.com/2011/02/17/the-application-could-not-be-launched-for-debugging-when-using-the-wp7-emulator/

Posted by 동동(이재동)
Windows Phone 72011. 11. 23. 13:26

마켓에 app을 올릴때 이런 에러가 난다면?

이미지 1

해당 프로젝트에서 오른쪽 버튼 눌러서

Assembly information 에서 nerialResource Lanuge를 설정한다.

참고 : http://stackoverflow.com/questions/6741455/the-neutralresourcelanguage-attribute-is-missing-on-the-entry-assembly

Posted by 동동(이재동)
Windows Phone 72011. 11. 21. 16:05

일단 UserControl을 하나 만들고

메인 페이지 xaml에 넣는다.

<uc:RadJobId x:Name="RadJobIDUserControl" Visibility="{Binding RadJobIdPopupVisiblity}"/>

이런식으로 넣었다. 이제 이 UserControl 안에 Button을 넣고

버튼을 클릭시에 메인페이지(상위 페이지)에 있는 메소드나 ViewModel에 접근해보겠다.

 

private void CancelBtn_Click(object sender, RoutedEventArgs e)
        {
            PhoneApplicationFrame frame = Application.Current.RootVisual as PhoneApplicationFrame;
            var parentView = frame.Content as ReserveTicketSelectView;
            var parentViewModel = parentView.DataContext as ReserveTicketSelectViewModel;
            parentViewModel.RadJobIdPopupVisiblity = Visibility.Collapsed;
        }

 

간단하다.

접근해서 viewModel의 Peroperty를 변경한 예제 이다.

Posted by 동동(이재동)
Windows Phone 72011. 11. 16. 17:19

코레일의 역정보를 어디서 가져오나 싶었더니 sqllite를 이용하여 가져왔다.

나도 그것을 복사해서 해볼려고 했었지만 외부에서 가져온 sqllite 파일의 인코딩이 UTF8이 아니라 UTF16이여서

읽혀지지가 않았다.

그래서 어짜피 로컬 파일이니 그냥 csv로 만들어서 넣었다.

내가 한 작업은 이렇다.

1. sqlLite Database Browser에서 아이폰소스에서 가져온 KorailDatabase.sqlite 파일을 로드 한다.

2. file - export-에서  csv 파일로 export한다.

3. 메모장으로 아까 저장한 csv 파일을 다른이름으로 저장하는데 인코딩을 UTF8로 다시 저장한다.

4. 이제 윈폰7에서 정상적으로 한글로 보이고 파싱한다.
 

만약 나중에 역이 업데이트 되었을때 아이폰소스에서 저 파일만 다시 받아서 저렇게 csv파일로 만들어서 윈폰에 넣으면 된다.

아래는 csv를 List로 만든 소스이다.

 

    private List<StationsModel> GetStationsList()
    {
        var resource = Application.GetResourceStream(new Uri(@"/GloryApp;component/Resources/KorailStations.csv", UriKind.Relative));

        StreamReader streamReader = new StreamReader(resource.Stream);
        string stations = streamReader.ReadToEnd();

        var StationsSplitData = stations.Split('\n');

        List<StationsModel> stationLists = new List<StationsModel>();

        foreach (var item in SkipData.First(StationsSplitData))
        {
            if (item == "")
                continue;

            var splitString = item.Split(',');

            stationLists.Add(new StationsModel()
            {
                code = splitString[0].Replace("\"", ""),
                lat = splitString[1].Replace("\"", ""),
                lng = splitString[2].Replace("\"", ""),
                title = splitString[3].Replace("\"", ""),
                ktx = splitString[4].Replace("\"", ""),
                indexgroup = splitString[5].Replace("\"", ""),
                maingroup = splitString[6].Replace("\"", "")
            });
        }

        return stationLists;
    }
}
Posted by 동동(이재동)
Windows Phone 72011. 11. 16. 16:14

CSV파일을 윈폰에서 읽을때 첫줄을 Skip 하고 싶을때 사용한다.

csv 첫줄에는 대부분 데이터들의 컬럼값 즉 메뉴 이름같은것이 들어가기때문에

첫줄을 제외한 나머지 데이터를 뽑을때 유용한다. 혹은 마지막데이터를 끊거나

풀 소스

/// <summary>
/// csv 파일을 읽을때 처음 한줄을 Skip 할때 사용
/// foreach문등에서 처음 인덱스와 끝의 인덱스를 감지 한다.
/// </summary>
public static class SkipData
{
    public class SkipFirst<T> : IEnumerable<T>
    {
        private IEnumerable<T> mEnum;

        public SkipFirst(IEnumerable<T> enm)
        {
            mEnum = enm;
        }

        #region IEnumerable<T> Members

        public IEnumerator<T> GetEnumerator()
        {
            IEnumerator<T> iter = mEnum.GetEnumerator();
            if (iter.MoveNext())
            {
                while (iter.MoveNext())
                {
                    yield return iter.Current;
                }
            }
        }

        #endregion IEnumerable<T> Members

        #region IEnumerable Members

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }

        #endregion IEnumerable Members
    }

    public class SkipLast<T> : IEnumerable<T>
    {
        private IEnumerable<T> mEnum;

        public SkipLast(IEnumerable<T> enm)
        {
            mEnum = enm;
        }

        #region IEnumerable<T> Members

        public IEnumerator<T> GetEnumerator()
        {
            IEnumerator<T> iter = mEnum.GetEnumerator();
            if (iter.MoveNext())
            {
                T curr = iter.Current;
                while (iter.MoveNext())
                {
                    yield return curr;
                    curr = iter.Current;
                }
            }
        }

        #endregion IEnumerable<T> Members

        #region IEnumerable Members

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }

        #endregion IEnumerable Members
    }

    static public SkipFirst<T> First<T>(IEnumerable<T> enm)
    {
        return new SkipFirst<T>(enm);
    }

    static public SkipLast<T> Last<T>(IEnumerable<T> enm)
    {
        return new SkipLast<T>(enm);
    }
}

참고 : http://honestillusion.com/blogs/blog_0/archive/2007/02/05/c-code-adding-skip-first-to-foreach.aspx

참고로 사용은 이렇게 한다.


foreach (var item in SkipData.First(StationsSplitData))
Posted by 동동(이재동)
Windows Phone 72011. 11. 11. 15:27

아… 대단하다 이것 때문에 하루종일 샤워 할때도.. 꿈꿀때도 아침에 일어날때도 계속 이것을 어떻게 해결해야하나 싶었다.

현재 윈폰용 코레일 앱을 만드는데 EUC-KR에 이어 난항을 겪었다.

사건의 발단은 이렇다.

코레일에서 Rest Sevice를 이용해서 XML등을 읽어와서 파싱하는데

예약 현황 같은것은 로그인을 해야만 가능한것이였다.

웹에서를 예로 들면

로그인 인증 페이지 URL을 접속 해야만 예약 현황을 볼수 있는 페이지를 볼수 있었다.

만약 로그인 인증 페이지 URL을 먼저 접속하지 않으면 예약 현황 페이지에서는 로그인을 해야만 볼수 있다라고 뜬다.

그래서 내가 한방법은 Webclient를 이용해서 로그인 인증 페이지를 먼저 접속 후 예약 현황 페이지를 다시 호출한것이였다.

하지만 그 방법 역시 작동을 안했다. 구글링을 해서 좀더 로우레벨로 해보기로 하여 HttpWebRequest로도 해보고 아이폰쪽 소스도 보고 별짓을 다 했다.

결국 해결한것은 바로 쿠키였다 철도청 관계자는 서버 세션 유지라고 해서 난 쿠키랑 아무런 관계가 없을줄 알았다. 여기서 시간을 엄청 소비했다.

태규형님에게 도움을 요청했고 비슷한 사례를 하나 찾아주셧다.

http://bytes.com/topic/net/answers/426631-web-service-session-winform-client

결국난 CookieContainer 를 설정해야 한다는것을 깨닫고

Webclient를 override해서 가능하다는것을 깨달았다.

http://social.msdn.microsoft.com/Forums/en/csharpgeneral/thread/149d545f-b605-4fce-b29a-2bfb1c51fbbe

하지만 그것은 WinForm에서는 작동했지만 윈폰에서는 약간의 보안문제로 다시 수정,보완을 하였다.

결국 성공.. 이틀동안의 삽질에 대한 눈물이 났다. ㅠㅠ

다음은 이틀 동안 고생해서 내가 만든 윈폰7용 소스이다. 이건 진짜 인터넷에 하나도 없다 ㅠㅠ

public class CookieAwareWebClient : WebClient
    {
        private CookieContainer m_container = new CookieContainer();

        [SecuritySafeCritical]
        public CookieAwareWebClient()
        {
        }

        protected override WebRequest GetWebRequest(Uri address)
        {
            WebRequest request = base.GetWebRequest(address);
            if (request is HttpWebRequest)
            {
                (request as HttpWebRequest).CookieContainer = m_container;
            }
            return request;
        }
    }

사용은 그냥

 _webClient.OpenReadAsync(new Uri(url));  _webClient.OpenReadCompleted 
 
를 사용하였다.             
Posted by 동동(이재동)
Windows Phone 72011. 11. 8. 11:46

이번에 코레일 프로젝트를 맞게 되었다.

하지만 코레일은 EUC-KR로 된 XML이였고 윈폰과 실버라이트는 지원하지 않았다.

하지만 어떤 고마우신분이 라이브러리를 제공해 주셧다 프로젝트 시작하기 3일전에… 타이밍!!!

일단 외부에서 EUC-KR로 된 xml파일을 윈폰에서 사용하는 방법

 

public void GetXmlData(Action<Dictionary<string, string>, Exception> callback, string url)
{
    WebClient webClient = new WebClient();
    webClient.OpenReadAsync(new Uri(url));
    webClient.OpenReadCompleted += (s, e) =>
        {
            Stream readStream = e.Result;
            Byte[] euckrXML = new Byte[readStream.Length];

            readStream.Read(euckrXML, 0, euckrXML.Length);
            readStream.Close();

            var temp = EUCKR_Unicode_Converter.GetUnicodeString(euckrXML);
            XmlReader reader = XmlReader.Create(new StringReader(temp));
            XElement xe = XElement.Load(reader);

            //상위 element data
            Dictionary<string, string> dict = new Dictionary<string, string>();
            foreach (var item in xe.Elements())
            {
                dict.Add(item.Name.LocalName, item.Value);
            }

            //다수의 하위 elements data
            var query = from item in xe.Descendants("trn_infos").Descendants("trn_info")
                        select item;

            List<Dictionary<string, string>> trnsInfos = new List<Dictionary<string, string>>();
            foreach (XElement item in query)
            {
                Dictionary<string, string> trnInfo = new Dictionary<string, string>();
                foreach (XElement subItem in item.Elements())
                {
                    trnInfo.Add(subItem.Name.LocalName, subItem.Value);
                }
                trnsInfos.Add(trnInfo);
            }

            //출력
            foreach (var item in trnsInfos)
            {
                foreach (var subItem in item)
                {
                    Debug.WriteLine("{0}:{1}", subItem.Key, subItem.Value);
                }
            }

            callback(dict, null);
        };
}

 

위의 XElement 까지만 참고하면 될꺼 같다.

나머지 소스는 그냥 xml을 dictionary로 바꾸기 위한 소스코드이다.

자 이제 euc-kr은 문제 없이 웹으로 부터 받아서 파싱 가능한 상태이다.

그렇다면 보낼때는 어떻게 해야할까?

내가 원하는 결과 값 : 서울 -> "%BC%AD%BF%EF"

이다. 원래 같았으면

string encodingResult = HttpUtility.UrlEncode(url);

이런식으로 urlencode를 이용하겠지만  이렇게

해서 해결하였다.

Byte[] temp = EUCKR_Unicode_Converter.GetEucKRString("서울");
StringBuilder sb = new StringBuilder();
foreach (byte b in temp)
{
    sb.AppendFormat("%{0:x}", b);
}

sb.tostring();

카일로님이 만드신 소스 정말 유용한거 같다.^^

원본 소스다.

Posted by 동동(이재동)
포트폴리오2011. 10. 19. 16:21

휴플에서 만든 최초의 소셜 게임입니다.

-Camera, Compass, Accerometer AP 사용
-WCF 웹서비스 연동

여러가지 기능이 있지만 설명은 일단 생략




아래는 디자이너 기백씨가 수정한 이미지



자세한 정보는 여기에

Posted by 동동(이재동)
포트폴리오2011. 10. 19. 16:17
걸으면서 타이핑을 할수 있는 앱입니다.

-자주쓰는 텍스트 저장기능
-SNS 연동기능(Twitter,Facebook)
-Camera 사용
-폰트 및 색 변경 기능




자세한 설명은 여기에

Posted by 동동(이재동)
포트폴리오2011. 10. 19. 16:13

휴즈플로우에 처음 입사후 맡은 프로젝트 입니다.

윈도우폰7이 실버라이트 기반이라서 머 여러가지 역경이 있었지만 무사히 마친 프로젝트 입니다.

구글링을 하면 더 자세한 설명과 동영상이 나옵니다.

자세한 설명은 여기에




 

Posted by 동동(이재동)
Windows Phone 72011. 5. 27. 18:43

마지막이다.

 

이제 메세지를 보낼 UI를 만들어보자 관리자를 위한 프로그램이다

 

난 그냥 쉬운 WPF로 만들었다.

 

일단 버튼 하나 만들고

 

private void ToastButton_Click(object sender, RoutedEventArgs e)
      {
          string appId = "1";
          //string baseUri = string.Format("http://localhost:19976/Notifications/GetSubscribers?appId={0}", appId);
          string baseUri = string.Format("http://192.168.10.174:6060/Notifications/GetSubscribers?appId={0}", appId);
 
          GetSubscribers(baseUri);
          
      }

 

 

private void GetSubscribers(string baseUri)
     {
         WebClient webclient = new WebClient();
         webclient.DownloadDataCompleted += new DownloadDataCompletedEventHandler(webclient_DownloadDataCompleted);
         webclient.DownloadStringCompleted += new DownloadStringCompletedEventHandler(webclient_DownloadStringCompleted);
         webclient.DownloadStringAsync(new Uri(baseUri));
     }

 

이렇게 WCF 를 호출해서 사용자 URI들을 받는다. (10명이 등록 되어 있으면 서버가 10개가 들어 있는 List를 보내줌)

 

void webclient_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
       {                           
           MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(e.Result));
           DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(List<Uri>));
           deserializedListUri = serializer.ReadObject(ms) as List<Uri>;
 
           SendToast();
       }

 

자 다운이 다 되면 List로  Deserialize 한후

 

private void SendToast()
       {
 
           HttpWebRequest sendNotificationRequest = (HttpWebRequest)WebRequest.Create(deserializedListUri[0]);
 
           // We will create a HTTPWebRequest that posts the toast notification to the Microsoft Push Notification Service.
           // HTTP POST is the only allowed method to send the notification.
           sendNotificationRequest.Method = "POST";
 
           // The optional custom header X-MessageID uniquely identifies a notification message. 
           // If it is present, the // same value is returned in the notification response. It must be a string that contains a UUID.
           // sendNotificationRequest.Headers.Add("X-MessageID", "<UUID>");
 
           var title = "test Title";
           var subtitle = "test SubTitle";
           // Create the toast message.
 
 
           string toastMessage = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
           "<wp:Notification xmlns:wp=\"WPNotification\">" +
              "<wp:Toast>" +
                   "<wp:Text1>" + title + "</wp:Text1>" +
                   "<wp:Text2>" + subtitle + "</wp:Text2>" +
              "</wp:Toast> " +
           "</wp:Notification>";
 
           // Sets the notification payload to send.
           byte[] notificationMessage = Encoding.Default.GetBytes(toastMessage);
 
           // Sets the web request content length.
           sendNotificationRequest.ContentLength = notificationMessage.Length;
           sendNotificationRequest.ContentType = "text/xml";
           sendNotificationRequest.Headers.Add("X-WindowsPhone-Target", "toast");
           sendNotificationRequest.Headers.Add("X-NotificationClass", "2");
 
           using (Stream requestStream = sendNotificationRequest.GetRequestStream())
           {
               requestStream.Write(notificationMessage, 0, notificationMessage.Length);
           }
 
           // Send the notification and get the response.
           HttpWebResponse response = (HttpWebResponse)sendNotificationRequest.GetResponse();
           string notificationStatus = response.Headers["X-NotificationStatus"];
           string notificationChannelStatus = response.Headers["X-SubscriptionStatus"];
           string deviceConnectionStatus = response.Headers["X-DeviceConnectionStatus"];
 
           // Display the response from the Microsoft Push Notification Service.  
           // Normally, error handling code would be here.  In the real world, because data connections are not always available,
           // notifications may need to be throttled back if the device cannot be reached.
 
           resultTextBlock.Text = notificationStatus + " | " + deviceConnectionStatus + " | " + notificationChannelStatus;
       }
 
이렇게 보낸다 xml 형식으로 만들어서 보내면 되며
 
상태들도 header정보를 받아서 볼수 있다.

Posted by 동동(이재동)
Windows Phone 72011. 5. 27. 18:37

자 이번에는 WCF Rest Service를 만들어 보자.

 

이것도 역시 WCF Rest Service 프로젝트 생성해서

 

[ServiceContract]
   [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
   [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
   public class Notifications
   {
       private static Dictionary<string,List<Uri>> subscribers = new Dictionary<string,List<Uri>>();
       private static object obj = new object();
 
       [WebInvoke(UriTemplate = "register?uri={uri}&appId={appId}", ResponseFormat = WebMessageFormat.Xml, Method = "GET")]
       public void Register(string uri,string appId)
       {            
           Uri channelUri = new Uri(uri, UriKind.Absolute);
           Subscribe(channelUri,appId);
       }
 
       private void Subscribe(Uri channelUri,string appId )
       {
           lock (obj)
           {
               if (subscribers.ContainsKey(appId) == false)
               {
                   subscribers.Add(appId, new List<Uri>());
               }
 
 
               if (!subscribers[appId].Exists((u) => u == channelUri))
               {
                   subscribers[appId].Add(channelUri);
               }
           }
           //OnSubscribed(channelUri, true);
       }
 
       [WebInvoke(UriTemplate = "GetSubscribers?appId={appId}", ResponseFormat = WebMessageFormat.Json, Method = "GET")]
       public List<Uri> GetSubscribers(string AppId)
       {
           return subscribers[AppId];
       }

 

귀찮아서 소스만 썻다 보면 알듯이

클라이언트가 Register 메소드를 호출하여 URI와 AppID(구분을 위해)

를 주면 그걸 그냥 List에 저장하는 형식이다.

나중에 이걸 DB로 저장하게 바꾸기만 하면 된다.



 

 

Posted by 동동(이재동)
Windows Phone 72011. 5. 27. 18:31

그냥 여러개로 나누어서 적어보았다.. ㅋㅋ 웬지 그게 더 멋있어 보여서 (헐…)

 

요즘엔 다 이렇게 하더라 ㅋㅋ

자 이제 윈폰 클라이언트 프로그램을 만들어보자..

 

일단 윈폰 프로젝트를 열고

 

private HttpNotificationChannel httpChannel;
  const string channelName = "TestAppUpdatesChannel";
  // Constructor
  public MainPage()
  {
      InitializeComponent();
 
      //Create the channel
 
      //만약 채널이 이미 있으면 
      httpChannel = HttpNotificationChannel.Find(channelName);
 
      //이벤트 등록
      if (httpChannel == null)
      {
          httpChannel = new HttpNotificationChannel(channelName, "HugeFlowAppTestService");
          httpChannel.Open();
          httpChannel.BindToShellToast();
      }           
 
      SubscribeToChannelEvents();
      SubscribeToService();
      
  }

 

채널을 등록하고 open하고 bind 한다.

bindToshellToast()는 망고버전에 나온 좋은 기능이다 더 편리해졌다 ㅋ

 

만약 이미 등록되어있다면

그냥 이벤트만 연결하고 클라이언트 URI를 서버에 전달한다.

 

private void SubscribeToChannelEvents()
       {
           httpChannel.ChannelUriUpdated += new EventHandler<NotificationChannelUriEventArgs>(httpChannel_ChannelUriUpdated);
           httpChannel.ShellToastNotificationReceived += new EventHandler<NotificationEventArgs>(httpChannel_ShellToastNotificationReceived);
       }

 

이렇게 이벤트 연결하고

void httpChannel_ShellToastNotificationReceived(object sender, NotificationEventArgs e)
       {
           StringBuilder message = new StringBuilder();
           string relativeUri = string.Empty;
 
           message.AppendFormat("Received Toast {0}:\n", DateTime.Now.ToShortTimeString());
 
           // Parse out the information that was part of the message.
           foreach (string key in e.Collection.Keys)
           {
               message.AppendFormat("{0}: {1}\n", key, e.Collection[key]);
 
               if (string.Compare(
                   key,
                   "wp:Param",
                   System.Globalization.CultureInfo.InvariantCulture,
                   System.Globalization.CompareOptions.IgnoreCase) == 0)
               {
                   relativeUri = e.Collection[key];
               }
           }
 
           // Display a dialog of all the fields in the toast.
           Dispatcher.BeginInvoke(() => MessageBox.Show(message.ToString()));
       }
       

 

이건 이제 메세지를 받았을때 프로그램에 보여주기 위한 이벤트이다. 메세지를 받았을때 메세지 박스로 띄워준다.

 

 

/// <summary>
 /// MS에서 받아온 url을 서버(WCF Service)에 보낸다.
 /// </summary>
 private void SubscribeToService()
 {
     string appid = "1";
     
     //string baseUri = "http://localhost:19976/Notifications/Register?uri={0}&appId={1}";
     string baseUri = "http://192.168.10.174:6060/Notifications/Register?uri={0}&appId={1}";        
 
     string theUri = String.Format(baseUri, httpChannel.ChannelUri.ToString(),appid);
 
     WebClient client = new WebClient();
     client.DownloadStringCompleted += (s, e) =>
         {
              if (e.Error == null)
              {
                  Dispatcher.BeginInvoke(() => UpdateStatus("Registration Success"));
              }
              else 
              {
                  Dispatcher.BeginInvoke(() => UpdateStatus(e.Error.Message));
              }
 
         };
     
     client.DownloadStringAsync(new Uri(theUri));
 }

 

이렇게 서버에게 URI를 보내 준다. WCF Rest 서비스니 웹처럼 파라미터를 넣어서 전달

 

이렇게 해서 클라이언트 완성


NotificationToastClient.zip

Posted by 동동(이재동)
wcf2011. 5. 17. 15:57

자 Rest Service를 만들어 보자

 

RestService의 최대강점은  멀티 플랫폼할때 좋다는거다..

 

인자도 그냥 URL형식으로 Get,Post 방법으로 보내면 되고 그렇게 되면 언어나 플랫폼에 상관없이

 

쓸수 있는 아주 편한 진정한 RIA 서비스가 된다.

 

첫번째

 

new-project 해서 새로운 프로젝트를 만들고

 

Online Templates로 간다.. 아마 비쥬얼 스튜디오 2010을 깔았다면 그냥 wcf service가 있을것이다.

 

하지만 우리는 WCF REST Service를 만들것이기때문에 online Template으로 가서 프로젝트를 만든다.

 

image

 

만든뒤에

 

Service1.cs가 보일것이다.

 

물론  이걸써도 돼지만 새롭게 만드는것도 나쁘지 않다.

 

나는 윈폰에서 쓸 Notification Server를 만들꺼기때문에 Notifications.cs란 class를 새로 만들었다.

 

[ServiceContract]
   [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
   [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
   public class Notifications
   {
       private static List<Uri> subscribers = new List<Uri>();
       private static object obj = new object();
 
       [WebInvoke(UriTemplate = "register?uri={uri}", ResponseFormat = WebMessageFormat.Json, Method = "GET")]
       public void Register(string uri)
       {
           // TODO: Return the instance of SampleItem with the given id
           Uri channelUri = new Uri(uri, UriKind.Absolute);
           Subscribe(channelUri);
       }

 

그리고 클래스위에 ServiceContract를 정의 하였으며

 

저렇게 메소드를 만들어서 인자를 받게 만들었다..

 

그리고 중요한 Global.aspx.cs에서

 

 

private void RegisterRoutes()
{
    // Edit the base address of Service1 by replacing the "Service1" string below
    RouteTable.Routes.Add(new ServiceRoute("Service1", new WebServiceHostFactory(), typeof(Service1)));
    RouteTable.Routes.Add(new ServiceRoute("Notifications", new WebServiceHostFactory(), typeof(Notifications)));
}

 

 

이렇게 추가하고 컴파일한후

 

http://localhost:19976/notifications

 

컴파일 뒤에 notifications를 붙여서 접속하면 접속이 잘된다.

 

이제 머 메소드를 붙여 넣든 마음대로 요리하면 된다.

 

아참 이 Registor 메소드를 부르는쪽에서는 이렇게 호출한다.

 

/// <summary>
/// MS에서 받아온 url을 서버(WCF Service)에 보낸다.
/// </summary>
private void SubscribeToService()
{
    string baseUri = "http://localhost:19976/Notifications/Register?uri={0}";        
 
    string theUri = String.Format(baseUri, httpChannel.ChannelUri.ToString());
 
    WebClient client = new WebClient();
    client.DownloadStringCompleted += (s, e) =>
        {
             if (e.Error == null)
             {
                 Dispatcher.BeginInvoke(() => UpdateStatus("Registration Success"));
             }
             else 
             {
                 Dispatcher.BeginInvoke(() => UpdateStatus(e.Error.Message));
             }
 
        };
    client.DownloadStringAsync(new Uri(theUri));
}

 

 

쉽다.

Posted by 동동(이재동)
Windows Phone 72011. 5. 3. 10:15

일단 링크로 대신 나중에 포스트

http://chriskoenig.net/2010/08/16/customizing-wp7-push-notification-tiles/

Posted by 동동(이재동)
Windows Phone 72011. 4. 26. 16:22

윈폰용도 폰인지라.. 모바일 광고를 넣을수가 있다.

 

일단 Microsoft Advertising SDK for wp7을 깔자

 

http://msdn.microsoft.com/en-us/library/ff973720(v=msads.10).aspx

 

그리고

 

레퍼런스에 참조하고 이런식으로 그냥 컨트롤을 xaml에 넣고

 

<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
            <ad:AdControl x:Name="AdControl" AdUnitId="29398 " ApplicationId="b1bc2b62-4f51-4f85-a69c-d28119424405"  VerticalAlignment="Bottom" AdModel="Contextual" Width="420" Height="80" Margin="11,0,25,234" />
        </Grid>

 

Behind코드에

 

메인에 꼭 이걸 써넣자

// Constructor
       public MainPage()
       {
           InitializeComponent();
           Microsoft.Advertising.Mobile.UI.AdControl.TestMode = false;
       }

 

저걸 하지 않았을 경우 광고가 나왔다가 바로 사라진다..

Posted by 동동(이재동)
Windows Phone 72011. 4. 25. 15:16

일단 폰 정보를 얻기 위해서

WMAppManifest.xml에 이걸 추가하고

 

<Capability Name="ID_CAP_IDENTITY_USER" />

<Capability Name="ID_CAP_IDENTITY_DEVICE" />
 
private string GetPhoneANID()
{
    object anid = UserExtendedProperties.GetValue("ANID");
    if (anid == null)
    {
        byte[] deviceId = (byte[])DeviceExtendedProperties.GetValue("DeviceUniqueId");
 
        string id = BitConverter.ToString(deviceId).Replace("-", "");
        anid = id;
    }
    else
    {
        anid = anid.ToString();
    }
 
    return anid as string;
}

이렇게 해서 얻어오면 된다.
Posted by 동동(이재동)
Windows Phone 72011. 4. 22. 13:50

WMAppManifest.xml 에

 

<Capability Name="ID_CAP_IDENTITY_DEVICE"/>

 

를 추가하고

 

string model = null;
object theModel = null;
 
if (Microsoft.Phone.Info.DeviceExtendedProperties.TryGetValue("DeviceName", out theModel))
    model = theModel as string;
MessageBox.Show(model);

 

를 코딩하면 된다.

 

출처 : http://www.nickharris.net/2011/01/finding-the-device-model-on-windows-phone-7/

Posted by 동동(이재동)
Windows Phone 72011. 3. 31. 17:54

이란 에러 메세지를 자주 본다.

 

만약 behind코드(xaml.cs)라면

 

Dispatcher.BeginInvoke(() =>
                                    {
                                        NavigationService.Navigate(new Uri("/Views/RecordView.xaml", UriKind.RelativeOrAbsolute));
                                    });

 

이렇게 쓰면 되겠지만

 

ViewModel 이나 Service에서는 어떻할까?

 

Deployment.Current.Dispatcher.BeginInvoke( ()=>
                       {
                           ServiceLocator.Current.LocationPermissionViewModel.NoButtonClick(null);
                       });

 

이렇게 쓰면 된다.

 

참조 : http://social.msdn.microsoft.com/Forums/en/adodotnetdataservices/thread/43177228-1ab2-4489-afea-89b0bf61bdd7

Posted by 동동(이재동)
Windows Phone 72011. 3. 31. 15:13
xaml 상단에 이렇게 datacontext를 연결하고
 
DataContext="{Binding BookViewModel, Source={StaticResource Locator}}"
 
<phone:PhoneApplicationPage
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
    xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:controls="clr-namespace:HugeFlow.FortuneCoins.Controls"
    xmlns:uc="clr-namespace:HugeFlow.FortuneCoins.Controls"
    xmlns:wp="clr-namespace:HugeFlow.Phone.Controls;assembly=HugeFlow.Phone.Controls"
    xmlns:Custom="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity" xmlns:HugeFlow_CommandPattern_Interactivity="clr-namespace:HugeFlow.CommandPattern.Interactivity;assembly=HugeFlow.MVVM" 
    x:Class="HugeFlow.FortuneCoins.Views.BookView"
    FontFamily="{StaticResource PhoneFontFamilyNormal}"
    FontSize="{StaticResource PhoneFontSizeNormal}"
    Foreground="{StaticResource PhoneForegroundBrush}"
    SupportedOrientations="Portrait" Orientation="Portrait"
    mc:Ignorable="d" d:DesignHeight="768" d:DesignWidth="480"    
    shell:SystemTray.IsVisible="False" DataContext="{Binding BookViewModel, Source={StaticResource Locator}}">
 
behind에서 datacontext를 연결한후
 
private LocationPermissionViewModel _viewModel;
 
     public LocationPermissionView()
     {
         InitializeComponent();
         _viewModel = this.DataContext as LocationPermissionViewModel;
     }
 
그리고 커맨드를 사용할 버튼 이벤트에 이렇게

private void NoButton_Click(object sender, RoutedEventArgs e)
      {
          _viewModel.NoButtonClickCommand.Execute(null);
      }
Posted by 동동(이재동)
Windows Phone 72011. 3. 25. 17:23

 

다운 받을수 있는 url

http://www.innovativetechguy.com/?p=13

 

 

image

 

이렇게 생겼는데 2가지 모드를 지원한다. 마켓 플레이스 모드로 찍으면 마켓플레이스에 올릴 480 680

 

으로 짤라서 찍고 other로 하면 에뮬레이터 자체를 찍는다.

 

유용한듯?

Posted by 동동(이재동)
Windows Phone 72011. 3. 24. 16:07
 about페이지에 버전을 적어야 할때 프로젝트에서 버전정보를 입력하고
 
Properties의 AssemblyInfo.cs에서 AssemblyVersion을 입력하 곤하는데
 
이걸 빼오는 법이다.
 
Assembly assem = System.Reflection.Assembly.GetExecutingAssembly();
           AssemblyName assemblyName = new AssemblyName(assem.FullName);
 
           Version = assemblyName.Version.ToString(3);
 
 

간단하다..

Posted by 동동(이재동)
Windows Phone 72011. 3. 24. 16:05

이건 정말 옛날부터 알았던건데 혹시나 까먹을까 해서 쓴다.

 

NavigationServce.Navigate를 이용해서 페이지를 이동할때

 

var uri = new Uri(string.Format("/HugeFlow.Phone.Controls;component/AboutControl/AboutPage.xaml?AppName={0}&Version={1}&SiteAddress={2}&EmailAddress={3}&Year={4}&Company={5}"
                , appName, version, siteAddress, emailAddress, year, companyName), UriKind.RelativeOrAbsolute);

 

이런식으로 파라미터를 줄수 있다 웹과 같다.

 

그렇다면 받는쪽에서는 어떡해 할까?

 

받는 페이지에는

 

protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
       {
           base.OnNavigatedTo(e);
 
           string appName;
           string version;            
           string siteAddress;
           string emailAddress;
           string year;
           string companyName;
 
           if (NavigationContext.QueryString.TryGetValue("AppName", out appName) == true)
           {
               AboutPageControl.AppName = appName;
           }
 
           if (NavigationContext.QueryString.TryGetValue("Version", out version) == true)
           {
               AboutPageControl.Version = version;
           }
 
           if (NavigationContext.QueryString.TryGetValue("SiteAddress", out siteAddress) == true)
           {
               AboutPageControl.SiteAddress = siteAddress;
           }
 
           if (NavigationContext.QueryString.TryGetValue("EmailAddress", out emailAddress) == true)
           {
               AboutPageControl.EmailAddress = emailAddress;
           }
 
           if (NavigationContext.QueryString.TryGetValue("Year", out year) == true)
           {
               AboutPageControl.Year = year;
           }
 
           if (NavigationContext.QueryString.TryGetValue("CompanyName", out companyName) == true)
           {
               AboutPageControl.CompanyName = companyName;
           }
       }

 

이렇게 하면 된다.

Posted by 동동(이재동)
Windows Phone 72011. 3. 21. 18:36

지금까지 UserControl만 주구장창 만들어보았으면

 

이번에는 Control을 만들어서 dll로 빼서 편리하게 사용해보자.

 

첨에는 프로젝트를 라이브러리 프로젝트로 하나 만든다.

 

그리고 일단 UI가 있는것은 스타일이 필요할테니 Theme 폴더안에 generic.xaml을 만들자

 

그리고 이렇게 입력하자

 

<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"    
    xmlns:system="clr-namespace:System;assembly=mscorlib"
    xmlns:c="clr-namespace:AboutPageControlLibrary"    
    xmlns:sys="clr-namespace:System.Windows;assembly=System.Windows" 
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
    mc:Ignorable="d">
    <Style TargetType="c:AboutPageControl">
        
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="c:AboutPageControl">                    
                    <Grid>
                        <ListBox x:Name="AppListBox"  Margin="30,0,0,0" />
                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
        

 

이렇게 해서 AboutPageControl을 만들고 그안에 단순히 ListBox만 하나 넣었다. x:name은 ApplistBox로 정했다.

 

자 이제

 

cs파일을 하나 만드는데 Control을 상속받자

 

public class AboutPageControl : Control

 

그리고 생성자를 만든다.

public AboutPageControl()
       {
           DefaultStyleKey = typeof(AboutPageControl);

 

이렇게 DefaultStylekey로 하여서 아까 generic.xaml에 정의된 스타일을 가져온다.

 

자 이렇게만 하고 프로젝트 하나 만들어서 여기 dll을 참조 한후 사용하면

 

ListBox가 보일것이다.(사실은 아무것도 안보일껏이다 itemSource가 없으니^^)

 

자 그럼 이제 Listbox에 ItemSource를 정의해보자.

 

일단 저기 generic.xaml에 정의한 스타일의 컨트롤을 호출을 해야 한다.

 

public override void OnApplyTemplate()
       {
           base.OnApplyTemplate();
           this._listBoxControl = GetTemplateChild("AppListBox") as ListBox;
       }

 

이렇게 OnApplyTemplate를 오버라이드 한후

 

GetTemplateChild를 이용해서 Listbox를 _ListBoxControl에 정의하였다. _listBoxControl은 전역변수에 이미 정의를 했다이로써 언제든지 ListBox를 쓸수 있게 되었다.

 

그후에 이제 이 Listbox Itemsource에 data를 넣어보자.

 

public AboutPageControl()
       {
           DefaultStyleKey = typeof(AboutPageControl);
           this.Loaded += new RoutedEventHandler(AboutPageControl_Loaded);
       }

 

loaded에 넣은 이유는 알것이다.

 

 

void AboutPageControl_Loaded(object sender, RoutedEventArgs e)
        {
            List<AppData> appDatas = new List<AppData>();
            appDatas.Add(new AppData() { Id = "App1", Name = "himan2", Description = "haha" });
            appDatas.Add(new AppData() { Id = "App1", Name = "himan2", Description = "haha" });
 
            _listBoxControl.ItemsSource = appDatas;
            _listBoxControl.ItemTemplate = ItemTemplate;

 

이렇게 itemsource를 넣었다.

 

그러면 이제 itemSource도 보일것이다. 근데 또 궁금증이 있다. itemTemplate은 어떻게 줄것인가?

Control이 아니라면 그냥 xaml상에서도 줄수 있지만 여기서 이렇게 behind로 해야만 했다.

저위에 정의 되어 있는 ItemTemplate은 이렇게 정의 해줘야 한다. 미리

 

public DataTemplate ItemTemplate
      {
          get { return (DataTemplate)GetValue(ItemTemplateProperty); }
          set { SetValue(ItemTemplateProperty, value); }
      }
 
      public static readonly DependencyProperty ItemTemplateProperty =
          DependencyProperty.Register("ItemTemplate", typeof(DataTemplate), typeof(AboutPageControl), new PropertyMetadata(OnItemTemplateChanged));
 
      protected static void OnItemTemplateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
      {
      }

 

사실 OnItemTemplateChanged는 의미가 없는듯 ;;

 

이렇게 정의 해두고 generic.xaml 에

 

<Setter Property="ItemTemplate" >            
           <Setter.Value>                
               <DataTemplate>
                   <Grid x:Name="grid">
                       <Grid.Resources>
                           <c:FileNameToFilePathImageConverter x:Name="FTFConverter" />
                       </Grid.Resources>
                       <Grid.ColumnDefinitions>
                           <ColumnDefinition Width="100" />
                           <ColumnDefinition />
                       </Grid.ColumnDefinitions>
                       <Grid.RowDefinitions >
                           <RowDefinition />
                           <RowDefinition />
                       </Grid.RowDefinitions>
                       <Image x:Name="image" Source="{Binding iconFileName, Converter={StaticResource FTFConverter}}"  Grid.RowSpan="2" Width="99" Height="99"/>
                       <TextBlock x:Name="textBlock" Text="{Binding Name}" Grid.Column="1" FontWeight="Bold" Margin="20,0,0,0"/>
                       <TextBlock Text="{Binding Description}" Grid.Column="1" Grid.Row="1" FontSize="16" Margin="20,0,0,0" TextWrapping="Wrap" />
                   </Grid>
               </DataTemplate>
       </Setter.Value>
       </Setter>

 

이렇게 Property에 이름을 ItemTemplate로 정의 한다면

 

ListBox에 ItemTemplate이 정의가 되어서 아주 멋있는 ListBox가 보여질것이다. 이미지와 글이 있는^^

 

이제 어떻게 컨트롤을 처음에 만들고 Listbox를 추가하며 그안에 itemSouce와 ItemTemplate을 정의 하는지 알려주었다

Posted by 동동(이재동)
Windows Phone 72011. 3. 21. 18:17

대부분 컨버터 쓸때

 

<phone:PhoneApplicationPage.Resources>
        <Converter:FileNameToFilePathImageConverter x:Key="FTFConverter" />        

 

이런식으로 phoneApplicationPage.Resources안에 넣는다.

 

그러면 Control을 만들려고 할때 쓰는 generic.xaml에서 쓸려면 어디에 넣어야 할까?

 

<Setter Property="ItemTemplate" >            
           <Setter.Value>                
               <DataTemplate>
                   <Grid x:Name="grid">
                       <Grid.Resources>
                           <c:FileNameToFilePathImageConverter x:Name="FTFConverter" />
                       </Grid.Resources>

 

그렇다 이런식으로 Grid.Resources같이  패널 안에 리소스를 만들어 쓰면 된다.

Posted by 동동(이재동)
Windows Phone 72011. 3. 21. 13:15

Webclient에서 인터넷에 xml을 다운 받아서 파싱을 하는데 프로그램을 다시 실행시키지 않는한

 

변경된 xml을 다시 읽어 왔을 때 내용이 변경이 되지 않았다..

 

무슨 이야기인가 하면 xml을 온라인에서 읽다가 xml내용이 변경되어서 다시 읽어왔는데

 

다시 읽어온 xml이 변경하기전 data를 넘겨준다는 이야기 이다.

 

아마 내생각에는 Caching  문제로 한번 읽어온 데이터는 간직하지 않나 싶은데?

 

 

 

Random random = new Random();
 
string XmlURL = "http://URL?UnUsed="+random.Next().ToString();

 

그래서 이렇게 URL뒤에 랜덤 파라미터를 붙여서 캐싱을 막아놓았다..

 

이건 머 예전 웹할때 웹 브라우저 캐싱 피할때 쓰는거랑 똑같다…

 

참고 : http://forums.silverlight.net/forums/p/14453/110001.aspx

Posted by 동동(이재동)